How to increase the speed of my background and game elements with time (SOLVED)

#1

Hi there Defold forum, you guys are the best im Albert from Digital Game World so i recently started developing this game (sorry im a total noob a programming in Lua so forgive me if my questions might seem dumb) any the game is called tap whizzard its supposed to be a 2d leveled and endless runner centered around tapping to maneuver obstacles i split my first theme Forest into layers and and programmed each layer to have a different speed for my parrallax effect but i ran into a problem yesterday for the endless part i want the background, big trees, tree, floor , and front grass to increase their scroll speed depending on how much time the player has been playing but im having issues achieving that can anyone help me (please im new and still learning Lua and Defold) here is a screenshot of the game.

0 Likes

#2

Here’s one method:

Create a lua module, something like this:

local M = {}
M.speed = 1
return M

Let’s say you save it in the ‘main’ folder, as “game_state.lua”…

In any script you have that moves things relative to the ground speed, require this module and use M.speed to multiply the speed you move things.

Something vaguely along these lines:

local game_state = require "main.game_state"

function update(self, dt)
    ...
    pos.x = pos.x - mySpeed * dt * game_state.speed
    ...
end

Then in any script that requires the module, you can adjust the game speed by modifying the speed multiplier, for example:

game_state.speed = 1.5
-- OR: 
game_state.speed = game_state.speed * 1.01

That’s one way to do it without modifying your existing code much. If I was doing it myself, I would swap things around a bit: store the base speed in the module in pixels/second rather than a multiplier, so it would be more intuitive and accurate to change. I would have one script for moving stuff with a “parallax depth multiplier” script property (default to 1) to control each object or layer’s parallax speed, relative to the ground speed.

Now that I think about it, game_state.playerSpeed or game_state.cameraSpeed would probably be clearer than just game_state.speed.


[Edit] I didn’t quite answer the original question…I would have one script (maybe your player script, or some game state manager script if you have one) that modifies game_state.speed. If you just want to smoothly increase the speed over time, just do something like this:

local acceleration = 0.01 -- A wild guess.
local game_state = require "main.game_state"
function update(self, dt)
    game_state.speed = game_state.speed * (1 + dt * acceleration)
end

That way it would accelerate on a curve, if you want it to be linear then it would be much easier if game_state.speed was in pixels/second, you could just do:

local acceleration = 1 -- maybe?
...
    game_state.speed = game_state.speed + dt * acceleration
5 Likes

#3

Thank you for replying but the layers are not accelerating still

1 Like

#4

I created a module using the

local M = {}
M.speed = 1
return M

and used local game state = require “main.game_state”(that’s the name of the LUA module I created) to call the module for each layer followed by

Local acceleration = 1
function update (self, dt)
 game_state.speed = game_state.speed + dt * acceleration 
end

but the floor stopped moving entirely

Let me explain my game logic as of now so I created 3 different images: Bg 1, Bg 2, Bg 3 same thing with my floor layer too: floor 1, floor2 floor 3 and foreground grass also: grass 1, grass 2 and grass 3 apart from my trees which were 11 total anyway I created different collections for each layer floor.collection, tree.collection etc and each of the collections had a script like so:

0 Likes

#5

Eg the floor script was:

Local pieces = { “floor0”, “floor1”, “floor2” }
function init(self)
self.speed = 350
end

function update(self, dt)
for I, p in ipairs (pieces)
local post = go.get_position§
if pos.x <= -960 then
pos.x = 1918 + (post.x + 960)
end
pos.x = pos.x - self.speed * dt
go.set_position (pos, p)
end
end

This was the script I used as the controller for all the different layer collections with different self.speed and pos.x integers for instance my Back ground self.speed = 250 tree self.speed = 500 floor self.speed = 600 and so on that’s how I got my endless scroll with parrallax effect but I want it to accelerate overtime while still maintaining their respective self.speed values so as to maintain my parrallax effect even while accelerating.

0 Likes

#6

Is this code copy-pasted? Do you get errors in the console? You have multiple typos which should all cause errors or crash. You capitalized ‘local’ in two places. You define ‘post’ but use ‘pos’ (mostly). You don’t have the ‘do’ after ‘for’.

Otherwise, the example line I gave should work:

pos.x = pos.x - mySpeed * dt * game_state.speed

(Replace ‘mySpeed’ with ‘self.speed’ of course, to match what you have already.)

So the only change you need to make is to multiply by ‘game_state.speed’, so the movement is affected by your module setting.

2 Likes

#7

so with any script i want to use the module on i should
local game_state = require “main.game_state”

function update (self, dt)
pos.x = pos.x - self.speed * dt * game_state.speed
end

0 Likes

#8

Yes and No. That will not be your entire script, you can keep what you already had and should only need to modify two lines:

Add: local game_state = require “main.game_state” to the top of the script. Requiring the module is the way you gain access to it, otherwise you would not be able to use it, ‘game_state’ would not exist in that script.

Change:
this: pos.x = pos.x - self.speed * dt
to this: pos.x = pos.x - self.speed * dt * game_state.speed

Does that make sense?

1 Like

#9

Sorry i haven’t replied in quite some time im taking my Grade 12 exams so i have been busy so at the end of the day what you said made lots of sense and it worked i put the “require” at the beginning of each script and added * game_state.speed then declared my
local acceleration = 0.01
also at the top of the script so this is what my script looks like:

--floor script
-- ground.script
-- require the game_state LUA module
local game_state = require("main.game_state")
--Declares a local variable for acceleration
local acceleration = 0.01

function on_message(self, message_id, message, sender)
	if message_id == hash("set_speed") then -- <1>
		self.speed = message.speed -- <2>
	end
end

local pieces = { "floor0", "floor1", "floor2" }--<1>
function init(self)
	self.speed = 600--speed in pixels
end
function update(self, dt)
	for i, p in ipairs(pieces) do -- <4>
		local pos = go.get_position(p)
		if pos.x <= -960 then -- <5>
			pos.x = 1918+ (pos.x + 960)
		end
		pos.x = pos.x - self.speed * dt * game_state.speed -- <6>
		game_state.speed = game_state.speed * (1 + dt * acceleration)--<7>
		go.set_position(pos, p) -- <8>
	end
end

but since this part of the game is endless i noticed something when the floor accelerated the faster it became the more the gap between the newly spawned floor image and the previous batch like so:

0 Likes

#10

Hello @digigameworld73,

Try switching the lines where you set pos.x and game_state.speed, because you are using the game speed and then you update the game speed, so first update the speed and then use it .

Cheers.

0 Likes

#11

Please explain more and or give an example of what you mean please to specify which lines im to switch because i switched the
pos.x = pos.x - self.speed * dt * game_state.speed
and the game_state.speed = game_state.speed * (1 + dt * acceleration)
but the same problem persists please specify or give an example or give me another method if you have one
Thanks

0 Likes

#12

Hello @digigameworld73,

I was just making a suggestion, I use a different approach, but in my experience the gap you are getting is due to applying in an incorrect moment the parameter dt, that is why I suggested to change those lines.

The other thing you can do is make explicit the operator precedence, something like:
pos.x = pos.x - (self.speed * dt) * game_state.speed)

or maybe:

pos.x = pos.x - (self.speed * (dt * game_state.speed))

Again, it is only a suggestion because you are the only one who knows the logic in your game.

Or you can try and post the whole project so everybody can look at the code and give you a better advice.

Cheers

0 Likes

#13

Not 100% sure if it’s causing this problem, but you are modifying game_state.speed on every update for every piece. That means it’s actually accelerating 3x as fast as you set it to, and each piece is getting a slightly different speed. I recommend changing game_state.speed in a completely separate script so you can’t make this mistake.

0 Likes

#14

So i going to create a new script for game state speed so how can i make it to pass that message to the other floor,bg,tree scripts or should i use a module instead

0 Likes

#15

Here is the project in a zip file sorry if somethings might be messy im still on alpha development
Tap Whizzard.zip (4.9 MB)

0 Likes

#16

Ooooh, you are right @ross.grams

Hey @digigameworld73, try @ross.grams suggestion, try something like:

function update(self, dt)

  game_state.speed = game_state.speed * (1 + dt * acceleration)

  for i, p in ipairs(pieces) do 
    local pos = go.get_position(p) 
    if pos.x &lt;= -960 then
      pos.x = 1918+ (pos.x + 960) 
    end 
    pos.x = pos.x - self.speed * dt * game_state.speed
    go.set_position(pos, p) -- &lt;8&gt; 
  end 
end 

Good luck and Cheers!

1 Like

#17

Thank you very much this worked 100% God bless

0 Likes