Howdy, Stranger!

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

snake by lines

edited September 2012 in Questions Posts: 97

Hi, can anybode help me code snake controled by 2 arrows moving in 360 degrees? what about drawing style? it is better to use lines or ellipse? thanks

Comments

  • Hi @Cabernet there are a few snake examples already shared on the forum. Just search for snake or look through the Code Sharing Category (look over here -->

  • yes but all of them have only 4 way movement on grid... I want to now how to figure out with snake moving in 360 degrees

  • Posts: 371

    Hey @Cabernet, I saw you commented on my snake project, so what you intend is to have a snake game which can go in any direction? I have a few comments on that:

    One:

    Nice twist on the classic game! My greatest change from the classic game that I thought of was shooting fireballs ;)

    Two:

    I hope you have previous programming experience, as this idea has many complicated parts

    1. The speed and direction of the snake would be tricky, with no grid
    2. The gameplay (I think) would be tricky, because you could double back on yourself (nearly) and twist your snake in odd angles.
    3. The control style would be tricky! Swipes? Turning by the arrows (like a car)
    

    Three

    I am thinking lines, I tried ellipses, and although looking cool, it was quite hard to see.

    Four

    I wouldn't mind cooking something up for you...

  • @Cabernet @Jordan you guys made me reminisce of a game i used to play. here's a link
    http://www.neopets.com/games/game.phtml?game_id=500&size=regular&quality=high&play=true

  • I like the idea and started to code a bit to find out how this could be solved. I came across some problems which would be interesting to see if somebody has a solution for.

    First i made the controls: Touching the screen on the left side turns left and touching right turns right. This just increases or decreases a number which is used as radians input for sin/cos to calculate the movement vector. Simply uses currenttouch, which is not perfect. Shold be done with touched function.

    Then I tried to create a display sized image and render an ellipse into it at the new location to get the trail. But that was very slow, I got only 3 fps or so. This happened when I called setContext(), so my first question is, if this can be made faster? The drawing of that large image every frame was fast enough.
    To avoid setContext() I tried the set function on the image, but even setting one pixel drops the frame rate from 60 to 10. Is there some trick to do that faster? Because having the playground in an image would make it easy to check the collision -> just call image:get on the location of the head of the snake to see if there is a trail.

    Finally I used the retained mode to draw the trail. That works fast, but I cant find a collision. So my final question is: Can I read the content of the current display (ogl color buffer) to check if there is a trail?

    Why did I use this approach? I have no grid and want to move freely. But I did not want to save the whole trail as polyline and render it each frame and also check the whole polyline for a collision. So this seems a simple solution... if the collision could be solved.

    Below you find the simple code for the retained mode approach. Of course, the touch handling should be done more stable and there are no borders. But it shows the concept:

    -- Snake360
    backingMode(RETAINED)
    
    direction = 0    -- Degrees in radians.
    curPos = vec2(WIDTH/2, HEIGHT/2)
    
    -- Use this function to perform your initial setup
    function setup()
        background(25, 25, 44, 255)
    end
    
    function draw()
        -- Change direction by touch:
        if CurrentTouch.tapCount >= 1 and (CurrentTouch.state == BEGAN or CurrentTouch.state == MOVING) then
            if CurrentTouch.x < WIDTH/2 then
                direction = direction - DeltaTime * 2
            elseif CurrentTouch.x > WIDTH/2 then
                direction = direction + DeltaTime * 2
            end
        end
    
        local oldPos = vec2(curPos.x, curPos.y)
    
        curPos.x = curPos.x + math.sin(direction) * DeltaTime * 150
        curPos.y = curPos.y + math.cos(direction) * DeltaTime * 150
    
        -- Draw into playground image:
        pushStyle()
            smooth()
            strokeWidth(10)
            stroke(255, 109, 0, 255)
            line(oldPos.x, oldPos.y, curPos.x, curPos.y)
        popStyle()
    end
    
  • BTW, there is a game in the store which has 360 freedom, it is called "Achtung".

  • This is exactly what I was looking for. Description is very good too. Thanks

  • A solution for collision checking is to create an array with smaller resolution than the display. I tried with 1/4 of size and it works nicely :-) I'm still interested, if this could be solved in other ways like I tried above, but it was too slow... it is a bit different to work in retained mode and it doesnt work on ipad3, so other solutions would be nicer for me.

  • dave1707dave1707 Mod
    Posts: 7,612

    Try this code for controlling the speed and direction of your object. See comments at the beginning of the code to use either variable or constant speed. You can change the values of speedVariable or speedFixed to get the overall speed you want to use.


    -- Here is a routine to control the direction  -- of an object based on where you touch the  -- screen or drag your finger. -- set fixedSpeed to true to move the object at a  -- constant speed. -- set fixedSpeed to false to move the object at a  -- speed thats faster the farther you touch  -- from the object. function setup()     displayMode(FULLSCREEN)     x=WIDTH/2     y=HEIGHT/2     sx=0     sy=0     speedVariable=50     speedFixed=3     fixedSpeed=true end function draw()     background(40,40,50)     fill(255,0,0)     ellipse(x,y,10,10)     x = x + sx     y = y + sy end function getDirection()     dx=CurrentTouch.x-x     dy=CurrentTouch.y-y     h=math.sqrt(dx*dx+dy*dy)     if fixedSpeed then         sx=dx*speedFixed/h         sy=dy*speedFixed/h     else         sx=dx/speedVariable         sy=dy/speedVariable     end end function touched(t)     getDirection() end
  • Hello @Cabernet. My contribution to coding freely-moving snakes, inspired by your question and this discussion, is here.

  • Posts: 730

    @KilamMalik taking your code as a starting point I've implemented a version with images.
    My solution was essentially to store the coordinates (or poly line as you said) and check the head position against the previous locations. I found interacting with images directly using get and set quite slow(well actually set rather than get), and though would give pixel point accuracy it's overkill here.

    I also got a wee bit carried away and implemented a eat the food to grow the snake function. I too haven't implemented screen boundary detection and the screen only flashes when a collision with itself occurs

    -- Snake360
    --backingMode(RETAINED)
    displayMode(FULLSCREEN)
    
    -- Use this function to perform your initial setup
    function setup()
        direction = 0    -- angle in radians.
        curPos = vec2(WIDTH/2, HEIGHT/2) -- position of snake head
        posArray={}-- table for coordinates
        snake=mesh()
        snakeimg=readImage("Cargo Bot:Star Filled")
        snake.texture=snakeimg
        food=mesh()
        foodimg=readImage("Cargo Bot:Smoke Particle")
        food.texture=foodimg
        foodPos =vec2(math.random(WIDTH-200)+100,math.random(HEIGHT-200)+100) -- initial position of food
        maxSize=50
    end
    
    function draw()
        snake:clear()
        food:clear()
        background(25, 25, 44, 255)
        -- Change direction by touch:
        if CurrentTouch.tapCount >= 1 and (CurrentTouch.state == BEGAN or CurrentTouch.state == MOVING) then
            if CurrentTouch.x < WIDTH/2 then
                direction = direction - DeltaTime * 2
            elseif CurrentTouch.x > WIDTH/2 then
                direction = direction + DeltaTime * 2
            end
        end
    --    store the previous position in a tableinserting it at the front
            local oldPos = vec2(curPos.x, curPos.y)
            table.insert(posArray,1,oldPos)
            --drop the tail off the snake according it the max size
            if #posArray>maxSize then
                table.remove(posArray)        
            end
    --        calculate the new head position
        curPos.x = curPos.x + math.sin(direction) * DeltaTime * 150
        curPos.y = curPos.y + math.cos(direction) * DeltaTime * 150
    
        --detect collision between head and food
        -- very rough - calculate straight line distance between head and food
            if math.sqrt((foodPos.x-curPos.x)^2+(foodPos.y-curPos.y)^2)<15 then
                --increase the snake size
                maxSize = maxSize + 30
                --create food in a new random location
                foodPos =vec2(math.random(WIDTH-200)+100,math.random(HEIGHT-200)+100)
            end
        -- position the food
        local foodid=food:addRect(foodPos.x,foodPos.y,20,20)
        food:setRectTex(foodid,0,0,1,1)
     
        --miss out last 10 as it won't be possible to turn that quick and stops collision with immediate neighbour
            for i=10,#posArray do
                local idx=snake:addRect(posArray[i].x,posArray[i].y,20,20)
                snake:setRectTex(idx,0,0,1,1)
                -- fade out the tail
                snake:setRectColor(idx,255,255,255,255-(255*i/#posArray))
                if math.sqrt((posArray[i].x-curPos.x)^2+(posArray[i].y-curPos.y)^2)<5 then
                     --game over, but at the moment flash a random background colour
                     background(math.random(255),math.random(255),math.random(255), 255)
                end
            end
        food:draw()
        snake:draw()
    end
    
  • Thanks @West for looking into that. I like that approach of using meshes and it is pretty fast even though you build up the rectangles each frame. I think thats the solution for @Cabernet question.

    I think I did not write that in detail, but I wanted to have an endless trail. Then you have to live as long as possible in one or multiplayer environment (like tron). Thats why I chose the approaches in my comments above. But I dont like the retained mode when it comes to e.g. picking up items.

    BTW, The star looks great when turning around corners... I will try that with retained mode :-)

    @Cabernet, I hope you dont mind if I create a game like that. Your idea seems a bit different but your post lead me to ideas for some gameplay... well, maybe more a game like "Achtung", but with some single player levels. its a small game so this could be the optimal first project for the app store for me... my mac mini arrived today :-) I hope retained mode works when compiled as ipa...

  • @KilamMalik Sound great! I am looking forward to your game... I want to develop some snake game but when i saw Achtung(thank you for this reminder) I decide to focus on something else... I am also looking for some mac mini or another mac device to start real developing for iOS. When your game will be in App store make sure to post about it.

    Sorry for my English ;) Cabernet

  • @West, finally I'm using your approach with meshes. I thought it would be too slow as I simply set the maximum length in your code higher. But I have missed, that you recreate the whole mesh each frame. you do that to cut the end, but I cluld just add rects as i want to keep the trail. thats now fast enough and I can have a trail of a few thousand rectangles :-)

Sign In or Register to comment.