Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Newbie Side Scrolling Question

edited July 2012 in General Posts: 115

As was mentioned in one of my earlier threads, I am developing a typical side scroller game in the theme of Fly With Me to keep a glider aloft with a tap on the screen. I am using juaxix's Sprint Animal example code as a starting point, editing as I go along to get the results that I need. Again, thank you very much juaxix for providing this most helpful code and to West for the character animation example code.

My question is instead of random backgrounds and collectible objects, how would one go about incorporating pre-drawn elements? I'm not looking for code per se but a nod in the right direction would be much appreciated. Is this a good time to use tables and if so, what would be the best way to use them?

How big should the background images be in order to preserve frame rate? Is a complete screen size graphic too large or should it be broken up into several image files per screen and deleted as they roll off screen? I want to use parallax scrolling for extra eye candy (I looked at an example using parallax scrolling that I have found here but a forum search did not turn up the code or the author, sorry) and wondered how the extra graphics will come in to play.

Searching the forum, I have read conflicting reports whether off screen graphics are culled or maybe not. Perhaps I missed the decision but could someone provide a definitive answer? Two of my three splash screens are full screen and I would like to know if they should somehow be removed from memory and if so how?

Again, this project will probably never get to the app store as this is only a very fulfilling hobby to help keep my old mind ticking and to see the immediate benefits on the iPad via Codea.

If my posts are too drawn out please let me know and I will certainly contract my questions. I do not want to be a burden to this great forum by no means.

Any help would be much appreciated.

Thanks in advance for those who may reply.

Tagged:

Comments

  • Posts: 742

    I don't think there is necessarily a right or wrong answer, it just depends what you are trying to do.

    In terms of your splash screens, provided you are only calling one of them at a time from your main draw function it shouldn't matter.

    I'm guessing the size of your sprites shouldn't matter either too much as long as you don't have too much overlap.

    The other consideration is how much storage space is used. Back in the olden days this was at a premium so smaller reusable blocks were used to make big maps. This is also an advantage that your playing area can be customised from the program rather than being hard wired into a big static image

    Here is the simple demo of parallax scrolling I suggested in an earlier thread (http://twolivesleft.com/Codea/Talk/discussion/comment/9020#Comment_9020) but I've stretched a sprite as the background. I've also added a simple array/table to control the sprite used in the ground. This could be expanded to a longer array and you could track the location within the array so you only generate the sprites that appear in the visible area.

    -- Use this function to perform your initial setup
    function setup()
        xpos=0
        grass={1,1,0,0,0,1,1,0,0,0}
    end
    
    -- This function gets called once every frame
    function draw()
    
    sprite("SpaceCute:Background",WIDTH/2,HEIGHT/2,WIDTH,HEIGHT)
    
        for i = 1,40 do
           sprite("Small World:Tree Round Dark", xpos/4+ 25*i-100, 90,40,50) 
        end  
            
        for i = 1,20 do
           sprite("Small World:Tree Round", xpos/2+ 50*i-100, 60,60,70) 
        end
            
        for i = 1,10 do
            if grass[i]==1 then
                sprite("Planet Cute:Grass Block", xpos+101*i-100, 0)
            else
                sprite("Planet Cute:Brown Block", xpos+101*i-100, 0)
            end
        end
        xpos=xpos-1
        --need to reset xpos at an appropriate point to get wraparound
    end
    

    Finally, meshes rather than sprites might be the way to go as I think they'll give you better performance but I've not looked into them in much detail.

  • Posts: 115

    Thanks for your thoughts, West. I thought about meshes as well but like you, haven't spent much time with them yet. I'll try a few things and see how they work out.

    Yes, this is the parallax example I was referring to that did not turn up in my forum search. Perhaps I misspelled it. Anyway, I liked it then and also how you added the new wraparound functionality. Thanks.

  • edited July 2012 Posts: 437

    Uhm, i think it would be nice to create some kind of running time ground generation algorithm , such like we are talking in this post:

    I'm coding the processing game in which Tiny Wings is based (Wave Spark : http://nmccoy.net/games/game04_wavespark/applet/index.html ) , I'm submiting the code here:
    https://gist.github.com/3123491
    and i need help to make it real :)
    Can you help me @Keebo?
    Stoling your post like a boss XD

  • Posts: 115

    @juaxix, I would be glad to help in any way that I can if you are serious. Being a newb with Codea/Lua, I don't how much help I can provide but it will be a great learning experience. Plus I think a successful ground generator would be quite useful for everyone interested in this type of function.

    Cutting and pasting to follow.

    Thanks for all of your contributions.

  • Posts: 742

    @Keebo
    Your post got me thinking so I put together a simple side scroller along the lines of the "helicopter game". It's super basic and not as smooth as I'd like so the next stage is to try out some meshes but meanwhile here is the code.

    -- Use this function to perform your initial setup
    function setup()
       displayMode(FULLSCREEN)
        --gameState is the current state of play
        -- 0 is the splash screen
        -- 1 is normal gameplay
        -- 2 is gameover
        gameState=0
    end
    
    -- This function gets called once every frame
    function draw()
    --One if statement checks what game state we are currently in and executes the relevant code
    if gameState==0 then
        --Draw the splash screen
        background(0,0,0,255)
        font("AmericanTypewriter-Bold")
        fontSize(40)
        --Set up a title
        text("Sideways Scroller Demo",WIDTH/2,HEIGHT/2)
        fontSize(25)
        --add your name
        text("by West",WIDTH/2,HEIGHT/2-50)
        --Draw a start button
        fill(127, 220, 23, 255)
        ellipse(WIDTH/2,HEIGHT/2-200,100)
        stroke(220, 217, 172, 255)
        fill(223, 230, 222, 255)
        fontSize(50)
        text("Go",WIDTH/2,HEIGHT/2-200)
        --Calculate the distance of the edge away from the centre of the button
        dist=math.sqrt(((CurrentTouch.x-WIDTH/2)^2)+((CurrentTouch.y-(HEIGHT/2)+200))^2)
        --check to see if the user has touched the button
        if CurrentTouch.state==ENDED and dist<50 then
            --put into the play game state
            gameState=1
            --Initialise some variables
            xpos=0 --used for the movement of the background
            speed=5 --initial speed
            speedCounter=0 --a counter to increment the speed
            speedMax=200 --the value at which the speed will increment
            topSpeed=50 --the top speed
            upthrust=0 --the upward force applied to the hero character
            herovel=0 --the vertical velocity of the hero character
            herox=100 --the horizontal position of the hero
            heroy=HEIGHT/2  -- the vertical position of the hero
            --an array of height values for the ground
            --add more values into the array to create a longer level
            ground={3,3,3,3,3,4,3,2,1,1,1,1,2,2,3,4,4,3,3,4,4,4,4,5,4,3}
            --an array of height values for the ceiling
            --make sure that the two arrays are the same length
              roof={3,3,2,3,4,4,5,6,7,6,6,5,4,4,4,3,2,3,4,5,6,5,5,4,3,2}   
            t=0.1 -- a time variable used to calculate the position and velocity between frames
            acc=0  --an acceleration variable calculated each frame
            grav=-10 --a constant gravitational force
            score=0  --the current score
            restartwait=0 --a timer for restarting the game at the end
        end           
    
    elseif gameState==1 then
    --Stretch an sprite to fill the background
    --As this is the furthest away thing draw first and everything else will be drawn on top
        sprite("SpaceCute:Background",WIDTH/2,HEIGHT/2,WIDTH,HEIGHT)
    
    --the screen in landscape will allow 12 sprites with a width of 100 to be drawn
    --try reducing the second number to 10 to see the effect (make sure you hold in landcsape)    
        for i = 1,12 do
    --the value in the current position (i) of the ground array is the number of blocks high to 
    --draw at the current position
            for h=1,ground[i] do
                --draw the sprite at the current x position i * width of one sprite with the xpos
                --offset which creates the movement
                --the y position is calculated as a multiplier of the the height
                sprite("Planet Cute:Ramp South",xpos+100*i-100,-40+70*h,100,100)
            end       
            --repeat the process for the ceiling
            for h=1,roof[i] do
                sprite("Planet Cute:Ramp South",xpos+100*i-100,HEIGHT+50-70*h,100,100)
            end           
        end
    
    --Display the hero sprite
        sprite("Planet Cute:Enemy Bug",herox,heroy,110,160)
    
    --Simple version with no gravity, touch above the hero sprite to move up and below to move down
    --handle a touch input from the user     
        if CurrentTouch.state == MOVING or CurrentTouch.state== BEGAN then
        if CurrentTouch.y > heroy then
              heroy = heroy + 3
            elseif CurrentTouch.y<heroy then
                heroy = heroy - 3
          end      
        end
    --Gravity based version, touch anywhere to provide upthrust to counter gravity
       -- if CurrentTouch.state == MOVING or CurrentTouch.state== BEGAN then    
       --     upthrust = upthrust + speed/2
       --     if upthrust>20 then
       --         upthrust=20
       --     end
       -- end
       -- if CurrentTouch.state==ENDED then
       --     upthrust=0
       -- end
       -- acc=upthrust+grav
    --equation of motion to calculate the displacement in the y direction s=ut+0.5at*t
       -- heroy=heroy+herovel*t+0.5*acc*t*t
    --equation of motion for the new velocity v=u+at
       -- herovel=herovel+acc*t
        
    --stop the sprite going off the top of the screen
    --redundant here, but if you wanted to have a narrower field of play then this what you would use
    --try replacing both HEIGHT with HEIGHT/1.5 to try it out
        if heroy>HEIGHT then
            heroy=HEIGHT
        end
        if heroy<0 then
            heroy=0
        end
    --dealing with collisions
    --normally we would have to check to see if the hero has hit anything on the screen
    --however as we are restricting the movement to up and down only then we only 
    --need to check the sprites in the same vertical location
        if heroy<(-40+70*(ground[2]+1)) then
            gameState=2
        end
        if heroy>(HEIGHT+70-70*(roof[2]+1)) then
            gameState=2
        end
        
    --xpos is a variable used to control the position of the sprites on the screen
    --the variable speed determines how much each sprite is moved each time the screen is redrawn
        xpos=xpos-speed
    --score is based on distance travelled
        score = score + speed
        fill(255, 255, 255, 255)
        text("Score: "..score,WIDTH/2,HEIGHT-30)
    --need to reset xpos at an appropriate point to get wraparound
        if xpos<-100 then
            xpos=0
    --store the value of the current first element of the array   
    --for example, for the array {a,b,c,d} store the first element a in the variable temp
            temp=ground[1]
            tempr=roof[1]
    --shift the ground array along by one, overwriting the first element by the second element,
    --the second element by the third element, etc, etc
    --Note the last element is not overwritten yet
    -- {a,b,c,d} becomes {b,c,d,d}
            for c=1,#ground-1 do
                ground[c]=ground[c+1]
                roof[c]=roof[c+1]
            end
    --Move the previously saved first element (saved in the temp variable)to the last position
    --{b,c,d,d} becomes {b,c,d,a}
            ground[#ground]=temp
            roof[#roof]=tempr
        end
    --get faster over time
        speedCounter = speedCounter + 1
        if speedCounter>speedMax then
            speed=speed+1
            speedCounter=0
    --set an upper limit on the speed
            if speed>topSpeed then
                speed=topSpeed
            end
        end 
    --game over state       
    elseif gameState==2 then   
        background(96, 77, 77, 255)   
        text("Game over",WIDTH/2,HEIGHT/2)
        text("Score:  "..score,WIDTH/2,HEIGHT/2-50)
    --add a delay to stop overspill from the gameplay restarting the game instantly
        if restartwait>100 then
              text("Tap screen to restart",WIDTH/2,HEIGHT/2-100)
        end    
        if CurrentTouch.state==BEGAN and restartwait>100 then
            gameState=0
        end
        restartwait = restartwait + 1
    end    
            
    end
    
    
  • Posts: 742

    Was messing about with it further. Using meshes does make it significantly smoother and faster

  • Posts: 115

    @West, this is very cool. I really like how you are not shy with commented lines. That really helps to understand what is going on in the code.

    I was amazed at the speed increase with meshes in your example in the other thread as well. Keep up the great work.

    Thanks again for sharing your knowledge.

  • Posts: 742

    No worries. Glad it was of help :-)

Sign In or Register to comment.