Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Primitive Angry Bird
#1
       
click the images to zoom in

Code:
'====================================
' Primitive Angry Bird
' It's just a demo of simple physics
'
'
'====================================

' Screen dimensions
set window "Primitive Angry Bird", 1000, 600,false
set redraw off

'color definition
black       = [0,0,0]
white       = [255,255,255]
green       = [0,100,0]
lightgreen  = [0,255,0]
brown       = [255,100,10]
gray        = [100,100,100]
red         = [255,0,0]

' Gravity, Friction, Ground
gravity     = 0.1   
friction    = 0.99   ' Friction to slow down movement
groundLevel = 350   

' Bird,Pig,Boxes
visible bird        = []
visible pig         = []
visible boxes       = [] 
Initialize(groundLevel)

' Mouse
startX      = 0 
startY      = 0


'----------------
' Main game loop
'----------------
while not keydown(KEY_ESCAPE,true)
    ' clear screen
    set color black
    cls
   
    ' info box
    set color white
    set caret 10,420
    wln "--------------------"
    wln "Primitive Angry Bird"
    wln "--------------------"
    wln
    wln "Drag the red cirle by pressing your left mouse button"
    wln "Then hit the green circle !"
    wln
    wln "Control Keys :"
    wln "- SPACE BAR    = restart"
    wln "- ESCAPE       = quit"
   
    ' Draw ground
    set color green
    draw rect 0, groundLevel, 1000, 50,true
    set color white
    draw rect 0, groundLevel, 1000, 50
   
    ' Draw bird
    set color red
    draw ellipse bird.x, bird.y, bird.size,bird.size,true
    set color white
    draw ellipse bird.x, bird.y, bird.size,bird.size
   
    ' Draw pig
    set color lightgreen
    draw ellipse pig.x, pig.y, pig.size, pig.size,true
    set color white
    draw ellipse pig.x, pig.y, pig.size, pig.size
   
    ' Draw boxes
    for i = 0 to 2
        set color brown
        draw rect boxes[i].x, boxes[i].y, boxes.size, boxes.size, true
        set color white 
        draw rect boxes[i].x, boxes[i].y, boxes.size, boxes.size
    next
   
    ' Handle mouse input
    if not mousebutton(0) then
        ' Start dragging
        startX = mousex()
        startY = mousey()
    else
        ' Show trajectory line while dragging
        set color gray
        draw line bird.x, bird.y, mousex(), mousey()
       
        ' Release bird and calculate velocity
        bird.vx = (startX - mousex()) / 10
        bird.vy = (startY - mousey()) / 10       
    endif
   
    'Handle keyboard input to restart the game
    if keydown(KEY_SPACE,true) then Initialize(groundLevel)
           
    ' Update bird position
    ' Apply gravity
    bird.vy = bird.vy + gravity
       
    ' Update position
    bird.x = bird.x + bird.vx
    bird.y = bird.y + bird.vy
       
    ' Apply friction
    bird.vx = bird.vx * friction
    bird.vy = bird.vy * friction
       
    ' Check for ground collision
    if bird.y >= groundLevel - bird.size then
        bird.y = groundLevel - bird.size
        bird.vy = -bird.vy * 0.7  ' Bounce with reduced energy
    endif
       
    ' Check for pig collision
    distance = ((bird.x - pig.x)^2 + (bird.y - pig.y)^2)^0.5
    if distance <= bird.size + pig.size then
        pig.vx = bird.vx * 0.5  ' Transfer some velocity to the pig
        pig.vy = bird.vy * 0.5
        pig.hit = true
           
        ' Update position
        bird.x = width()+500
    endif
       
    ' Check for boxes and bird collisions
    for i = 0 to 2
        if bird.x + bird.size > boxes[i].x and bird.x - bird.size < boxes[i].x + boxes.size and
            bird.y + bird.size > boxes[i].y and bird.y - bird.size < boxes[i].y + boxes.size then
           
            ' Resolve overlap by moving bird away from box
            dx = bird.x - (boxes[i].x + boxes.size / 2)
            dy = bird.y - (boxes[i].y + boxes.size / 2)
            distance = (dx^2 + dy^2)^0.5
           
            if distance < bird.size + boxes.size / 2 then
                    ' Move bird away from box
                    overlap = (bird.size + boxes.size / 2) - distance
                    bird.x = bird.x + (dx / distance) * overlap
                    bird.y = bird.y + (dy / distance) * overlap
                   
                    ' Transfer velocity between bird and box
                    tempVx = bird.vx
                    tempVy = bird.vy
                    bird.vx = boxes[i].vx * 0.5
                    bird.vy = boxes[i].vy * 0.5
                    boxes[i].vx = tempVx * 0.5
                    boxes[i].vy = tempVy * 0.5
            endif
            boxes.hit = true
        endif
    next 
   
    if boxes.hit or pig.hit then
        ' Update pig position
        pig.y = pig.y + pig.vy
        pig.x = pig.x + pig.vx
       
        ' Apply gravity to pig
        pig.vy = pig.vy + gravity
    endif
   
    ' Check for ground collision for pig
    if pig.y >= groundLevel - pig.size then
        pig.y = groundLevel - pig.size
        pig.vy = -pig.vy * 0.5  ' Bounce with reduced energy
        pig.vx = -pig.vx * 0.5
    endif
   
    ' Update box positions
    if boxes.hit then
        for i = 0 to 2
            boxes[i].y = boxes[i].y + boxes[i].vy
            boxes[i].x = boxes[i].x + boxes[i].vx
           
            ' Apply gravity to boxes
            boxes[i].vy = boxes[i].vy + gravity
           
            ' Check for ground collision for boxes
            if boxes[i].y >= groundLevel - boxes.size then
                boxes[i].y = groundLevel - boxes.size
                boxes[i].vy = -boxes[i].vy * 0.01  ' Bounce with reduced energy
                boxes[i].vx = -boxes[i].vx * 0.01
            endif
        next
    endif
   
    'Check for collisions between boxes
    for i = 0 to 2
        for j = 0 to 2
            ' Check if boxes overlap
            if boxes[i].x < boxes[j].x + boxes.size and boxes[i].x + boxes.size > boxes[j].x and
               boxes[i].y < boxes[j].y + boxes.size and boxes[i].y + boxes.size > boxes[j].y then
               
                ' Resolve overlap by moving boxes apart
                dx = boxes[j].x - boxes[i].x
                dy = boxes[j].y - boxes[i].y
                overlapX = boxes.size - abs(dx)
                overlapY = boxes.size - abs(dy)
               
                if overlapX < overlapY then
                    ' Resolve horizontally
                    if dx < 0 then
                        boxes[i].x = boxes[i].x - overlapX+rnd(2,6)
                        boxes[j].x = boxes[j].x + overlapX+rnd(2,6)
                    else
                        boxes[i].x = boxes[i].x + overlapX+rnd(2,6)
                        boxes[j].x = boxes[j].x - overlapX+rnd(2,6)
                    endif
                else
                    ' Resolve vertically
                    if dy < 0 then
                        boxes[i].y = boxes[i].y - overlapY
                        boxes[j].y = boxes[j].y + overlapY
                    else
                        boxes[i].y = boxes[i].y + overlapY
                        boxes[j].y = boxes[j].y - overlapY
                    endif
                endif
            endif
        next
    next
   
    'Check for collisions between pig and boxes
    for i = 0 to 2
        'Check if pig overlaps with box
        if pig.x + pig.size > boxes[i].x and pig.x - pig.size < boxes[i].x + boxes.size and
           pig.y + pig.size > boxes[i].y and pig.y - pig.size < boxes[i].y + boxes.size then
            ' Resolve overlap
            dx = (pig.x - (boxes[i].x + boxes.size / 2))
            dy = (pig.y - (boxes[i].y + boxes.size / 2))
            distance = (dx^2 + dy^2)^0.5
           
            if distance < pig.size + boxes.size / 2 then
                ' Move pig away from box
                overlap = (pig.size + boxes.size / 2) - distance
                pig.x = pig.x + (dx / distance) * overlap
                pig.y = pig.y + (dy / distance) * overlap
               
                ' Transfer velocity between pig and box
                tempVx = pig.vx
                tempVy = pig.vy
                pig.vy = boxes[i].vx * 0.5
                pig.vy = boxes[i].vy * 0.5
                boxes[i].vx = tempVx * 0.5
                boxes[i].vy = tempVy * 0.5
            endif
        endif
    next
   
    ' Reset bird if it goes off-screen
    if bird.x < 0 or bird.x > width() or bird.y > height() or bird.y < 0 then
        bird.x = 100
        bird.y = groundLevel - bird.size
        bird.vx = 0
        bird.vy = 0
    endif
   
    ' Refresh screen
    fwait 60
    redraw
wend


'----------
' FUNCTION
'----------
function Initialize(groundLevel)
    ' Bird properties
    bird.size   = 10                       
    bird.x      = 100                       
    bird.y      = groundLevel - bird.size   
    bird.vx     = 0                         ' Horizontal velocity
    bird.vy     = 0                         ' Vertical velocity
   
    ' Pig properties
    pig.size    = 15                                   
    pig.x       = 700                                   ' Pig's x position
    pig.y       = groundLevel - pig.size - 3 * 30       ' Pig's y position (on top of boxes)
    pig.vx      = 0                                     ' Pig's horizontal velocity
    pig.vy      = 0                                     ' Pig's vertical velocity
    pig.hit     = false
   
    ' Box properties (stack of 3 boxes)
    boxes.size     = 30                                 ' Size of each box (width and height)   
    for i = 0 to 2
        boxes[i] = []
        boxes[i].x = pig.x-pig.size                      ' Staggered x positions
        boxes[i].y = groundLevel - (i + 1) * boxes.size  ' Stacked y positions
        boxes[i].vx = 0                                  ' Horizontal velocity
        boxes[i].vy = 0                                  ' Vertical velocity
    next
    boxes.hit = false
endfunc
Reply
#2
Ooh, I'll check it out after work Smile
Reply
#3
Thanks 1micha.elok, love the simple physics, but really struggled with the control to move the ball - it just didn't seem to want to go where I wanted it to Smile Quite possibly an issue more with me than the program Smile Smile
Reply
#4
Hehe, the controls feel a bit wonky (in a fun way) but I quite enjoyed playing around with them! It all looks promising Smile
Reply
#5
Figuring out control was an issue at first but eventually got the hang of it... Cool physics demo... One minor flaw... You seem to have forgotten the aliens? lol Eager to see what's next...
Logic is the beginning of wisdom.
Reply
#6
I'm currently working on a primitive version of angry birds, and it's been an exciting challenge ! I was particularly amazed by a Small pinball game by Kevin using Marcus' circle-line collision routines https://naalaa.com/forum/thread-129.html - It really inspired me.

Johnno, would you be interested in developing a simple physics engine together as I saw you once said something about simple physics enginee in Naalaa https://www.naalaa.com/forum/thread-93.html ? It could be a great learning experience, and as a starting point, we could draft some pseudocode or create basic functions such as gravity, friction, center of mass, velocity, collision of objects etc. It would be exciting to break down these core principles and build something solid from the ground up ! If you are intereted to work together with me to build simple physics library, let's do it Big Grin
Reply
#7
1micha.elok... Ah. I had to look up that reference just to refresh the memory... Yes, I remember asking about an engine, as I had seen other languages had an engine, in varying degrees of complexity. I remember asking if N7 could do it and "how" as I had no idea how to go about it... I would be honoured to participate but, be warned, my skill in math is not very good. That being said, if I can help in any way, I will... Just don't expect bone-rattling algorithms or jaw-dropping graphics... lol

Coordinating times could be interesting, as I live on the other side of this planet... lol In the meantime I will begin to research what a physics engine consists of... *gulp*
Logic is the beginning of wisdom.
Reply
#8
(03-14-2025, 04:59 AM)johnno56 Wrote: 1micha.elok... Ah. I had to look up that reference just to refresh the memory... Yes, I remember asking about an engine, as I had seen other languages had an engine, in varying degrees of complexity. I remember asking if N7 could do it and "how" as I had no idea how to go about it... I would be honoured to participate but, be warned, my skill in math is not very good. That being said, if I can help in any way, I will... Just don't expect bone-rattling algorithms or jaw-dropping graphics... lol

Coordinating times could be interesting, as I live on the other side of this planet... lol In the meantime I will begin to research what a physics engine consists of... *gulp*

Great, Johnno ! Even I don't know how far we can build the physics engine. Perhaps some physics in the Primitive Angry Bird are our starting point, and I am making a simple physics on a bridge. I'll make a new post then here https://naalaa.com/forum/thread-206.html

Meanwhile, happy Sunday and enjoy the Autumn in the southern hemisphere !
Reply
#9
Autumn... Yeah... 34C yesterday... 15C and raining today... Who knew, right?

I have checked out the "bridge"... that one will take me a while to get my head around it... lol Been looking through a lot of video clips etc in reference to engines, concepts and design... Pretty much all of them introduce some serious math to calculate not just collision detection but collision resolution, velocity, delta time, mass, acceleration... I am beginning to hate Isaac Newton... lol Most of the listings may as well have been written in Greek... I have been looking at some Javascript listings. They seem easier to read but I do not know enough of JS to convert to anything... I will go over your two demos and see what I can learn... In the meantime... Many years back I managed to convert a simple water-flow demo into sdlbasic ... if I can find it, I will try to convert it to N7, but uncertain as to where its or even if it exists at all... lol Again, thanks for the demos...

Gotta get some sleep... I'll "hit the books" in the morning... "after" my coffee of course... lol
Logic is the beginning of wisdom.
Reply
#10
"The code is simply an attempt to simulate a rectangle falling from the top to the ground. Please be aware that there are still some bugs and errors, which do not accurately reflect real-world physics."

https://naalaa.com/forum/thread-210.html
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)