Laggy game

Hello,

So I am currently in the process of making my own version of Pong that has a menu and levels, I have reached a stage though where I have noticed the game start to lag when I run the code on my iPad. This is my first time making a game so I have a hunch that how I have structured my code is the reason it’s so slow, so I will try to explain how I have gone about it.

My game has menu, a paddle selector and a level selector, as well as an in game state. I have turned each of these different screen states into separate classes, in setup() I initialise them all and then call their different functions inside draw() ( inside the main function). However each function coming from these classes is surrounded by an if statement, so the menu screen will only draw if MENUSTATE == true else it will go to the next if statement till it finds a Game state that is true so it can run the code for that classes function. I will add screen shots to help understand what I mean if not I am happy to re word this.

Anyway, is this way of organising my classes using lots of memory because all the games classes are existing but not being used?

I also have a handful of 1000x1000 images in my game which could be the source of slowing the game?

Thanks

I don’t think you’ve shown enough code here to isolate a problem. In Codea’s main project screen, tap and hold on your project icon and choose Export and then Copy Project Code and paste it here and maybe someone can dig in some more.

Okay thankyou

if you have a lot of print statements in the output panel that will eventually slow things down a lot.

@rydergaz Instead of having so many seperate if statements, change them to if else statements.

If ONEPLAYERSTATE == true then
        newpaddle:touched(touch)
elseif MENUSTATE == true then
        menu:touched(touch) 
elseif SELECTORSTATE == true then
        selector:touched(touch)
elseif LEVELSELECTORSTATE == true then
        levelselector:touched(touch)
end

@rydergaz You could add the line of code below for testing purposes just to see how many frames per second you’re running at. 60 is the max.

    text(1//DeltaTime,WIDTH/2,HEIGHT-25)
~~

@rydergaz Here’s a simple example of a pong game that runs at approx 59 or 60 FPS on my iPad Air. Adding code to check for touch to determine where the paddles should be wouldn’t affect the FPS much, maybe 1 FPS less. So if you’re running a lot slower than this, then you have something else that’s slowing your code down because the basic code of pong shouldn’t.

EDIT: Added code for touch and score. Slide your finger near the edge to move the paddle.

supportedOrientations(PORTRAIT_ANY)
displayMode(FULLSCREEN)
function setup()
    p1Total,p2Total=0,0
    rectMode(CENTER)
    bx,by=WIDTH/2,HEIGHT/2
    vx=math.random(5,8)
    vy=math.random(8,16)
    p1x,p2x=WIDTH/2,WIDTH/2
end

function draw()
    background(40, 40, 50)
    fill(255)
    text(1//DeltaTime,50,HEIGHT-25)
    text(p1Total,WIDTH/2,HEIGHT-50)
    text(p2Total,WIDTH/2,50)
    bx=bx+vx
    by=by+vy
    if bx>WIDTH or bx<0 then
        vx=-vx
    end
    if by>HEIGHT then
        p2Total=p2Total+1
        vy=-vy
    end
    if by<0 then
        p1Total=p1Total+1
        vy=-vy
    end
    rect(p1x,HEIGHT-100,100,25)
    rect(p2x,100,100,25)
    ellipse(bx,by,20)
    if bx>p1x-50 and bx<p1x+50 and by>HEIGHT-115 and by<HEIGHT-95 then
        vy=-vy
    end
    if bx>p2x-50 and bx<p2x+50 and by>95 and by<115 then
        vy=-vy
    end
end

function touched(t)
    if t.state==MOVING then
        if t.y>HEIGHT/2 then
            p1x=p1x+t.deltaX
        else
            p2x=p2x+t.deltaX            
        end
    end
end

Yeah, Pong is pretty simple and there shouldn’t inherently be any performance issues with it (which is why I asked to see the full code). I don’t want to toot my own horn (well, okay, I’m lying), but I’ve been working on a rather large project entirely within Codea that has tons going on each frame. You can see a slightly out of date video here: https://youtube.com/watch?v=i4qMxG1UDcc

@rydergaz I added code to the above example to control each paddle by sliding your finger back and forth. Also added code to score when the ball hits the wall behind the paddles. The code still runs at approx 59 FPS.

Some suggestions (your game looks pretty good by the way):

  • Instead of using different variables for each of your game states, try using a single variable and change it to your current state, like "MENU", "LEVELSELECTOR", "GAME", … (you probably see what I mean).
    A code example:
function setup()
  GAME_STATE = "MENU"
end

function draw()
  if GAME_STATE == "MENU" then
    -- draw your menu here
  elseif GAME_STATE == "LEVELSELECTOR" then
    -- draw your level selector
  elseif GAME_STATE == "GAME" then
    -- draw paddles, ball, and score
  end
end
  • Only setup your variables when you need them, and when the game is over, you can set them to nil and collectgarbage().
    When the game starts:
function setupGame()
  paddle1 = Paddle(WIDTH/2,HEIGHT-80,"Pink")
  paddle2 = Paddle(WIDTH/2,80,"Blue")
  ball = Ball(WIDTH/2,HEIGHT/2)
end

When the game is over:

paddle1 = nil
paddle2 = nil
ball = nil
collectgarbage()

(That should probably help)

  • As @piinthesky hinted, many calls to print inside draw can drastically slow down your game.
  • Finally, check out this link and this (more advanced) pdf guide, both not written by me.

Hope this helps.

I tried outputting the frame rate and it changes quite rapidly but it seems to bounce between 50 and 60 and down to 40 now and again too.

Thanks for the reply @em2 that’s super helpful! if your setting everything to nil what does garbage collection remove?

Also what is the best way to call a method of a class from a method of the same class .e.g

function Example:bounce()

X = X + 10

end

function Example:draw(Example)

Example.bounce

Print(X)

end

@rydergaz Here’s an example of a way to call a class function from another function of the same class.

function setup()
    t1=test("t1=",36,12)
    t2=test("t2=",12,2)
    t1:print()
    t2:print()
end

function draw()
    background(40, 40, 50)
end

test=class()

function test:init(v,x,y)
    self.v=v
    self.x=x
    self.y=y
end

function test:print()
    print(self.v,self.x,self.y)
    print( self:calc() )     -- call a function in the same class
end

function test:calc()
    return self.x+self.y , self.x*self.y , self.x/self.y
end

@rydergaz I think collectgarbage is supposed to clear unused values from memory. Check out this link for an explanation (I’m not an expert at this). An example:

-- Quick memory check function
function checkMem()
    return string.format("%g kB\
",collectgarbage"count")
end

function setup()
    print"Initital Memory Usage:"
    print(checkMem()) -- check initial memory usage
    -- create a table with 10000 subtables
    t = {}
    for i = 1, 10000 do
        t[i] = {}
    end
    
    print"Memory after creating table with 10000 items:"
    print(checkMem()) -- check again
    t = nil -- set t to nil (table is still in memory)
    
    print"Memory after setting table to nil:"
    print(checkMem()) -- check again
    
    collectgarbage()
    print"Memory after collecting garbage:"
    print(checkMem())
end

Comments and print statements in the code should explain everything. collectgarbage "count" returns memory usage in kilobytes.

Instead of branching if/ else statements, why not use classes to model different game states?


-- some states

--# MenuState
MenuState = class()

function MenuState:draw()
    -- draw menu
end

function MenuState:touched(touch)
    --handles touches
end

--# LevelSelectorState
LevelSelectorState = class()

function LevelSelectorState:draw()
    -- draw level select
end

--# GameState
GameState = class()

function GameState:draw()
    -- draw game
end

--# Main
-- in setup you'd have:

currentState = MenuState()

-- then in draw, no need for a long if/ else block you just have:

currentState:draw()

--likewise in touched:

function touched(touch)
    currentState:touched(touch)
end

-- to change state, eg, if the player dies, you put
currentState = GameOver()

This kind of simple state machine will really help to keep code encapsulated.

If you want to get fancy, you could enforce rules about which states are allowed to follow other states (eg you can only get to the GameOver state from the GameState), or implement a stack of states in an array (so you can pop from PauseState back to GameState by removing the last item from the state stack).

All of this is good general information, but I feel like everyone is focusing on a handful of “if” branches that won’t make any measurable performance difference here. Whatever is causing OP’s laggy issues almost certainly has nothing with this scene and state management business. More likely it is something simpler - drawing images that are way bigger than they need to be, drawing more often than necessary, etc.

@BigZaphod you’re right

Thank you all, I’ve sorted out the lagginness, was due to print statements.

@yojimbo2000 I made classes for the different game states and then initialized them all in the main setup() and then used if statements to call the different classes draw functions. Is that not a similar method to what you are saying?

ahhh, thought so!

@rydergaz

nearly there, but you could make it so much better by using a pointer to the current state, like it my suggestion above currentState = gameState or whatever. Long if else blocks are increasingly painful to read and maintain the more states that you add to the game, especially if you need to have them in draw, touched, orientationChanged etc.