Schlagwort-Archive: game

Monkey: asteroids game example

Strict

Import mojo

Global game:MyGame

Function Main:Int()
    game = New MyGame
    Return 0
End Function

Const PDM_smlparticle%=0
Const PDM_medparticle%=1
Const PDM_bigparticle%=2
Const PDM_spark%=3

Global ASTEROIDS_NUM% = 6
Global ASTEROIDS_SIZE% = 4

' Store the device width and height
Global SCREEN_WIDTH%
Global SCREEN_HEIGHT%
' Half of SCREEN_WIDTH and HEIGHT
Global SCREEN_WIDTH2%
Global SCREEN_HEIGHT2%

' Used for delta timing movement
Global dt:DeltaTimer

' Screen states
Const STATE_TITLE% = 1
Const STATE_GAME% = 2
Const STATE_GAME_OVER% = 3

Class MyGame Extends App

Field player:Player
Field cg%, cr%, cb%
Field level% = 1
Field score% = 0
Field bestScore% = 0

Field FPS% = 60
' Current game state
Global gameState:Int = STATE_TITLE

Method OnCreate:Int()
    ' Store the device width and height
    SCREEN_WIDTH = DeviceWidth()
    SCREEN_HEIGHT = DeviceHeight()
    SCREEN_WIDTH2 = SCREEN_WIDTH / 2
    SCREEN_HEIGHT2 = SCREEN_HEIGHT / 2
    ' Set the Random seed
    Seed = Millisecs()
    ' Create the delta timer
    dt = New DeltaTimer(FPS)
    SetUpdateRate FPS

    reset()
    Return 0   
End Method

Method OnLoading:Int()
    Cls 0,0,0
    DrawText("Loading", SCREEN_WIDTH2, SCREEN_HEIGHT2, 0.5, 0)
    Return 0
End Method

Method OnUpdate:Int()
    FPSCounter.update()
    dt.UpdateDelta()

    Select gameState
    Case STATE_TITLE
        Asteroid.updateAll()
        If KeyHit(KEY_SPACE)
           setState(STATE_GAME)
        Endif   
    Case STATE_GAME
        player.Update()
        Bullet.updateAll()
        Asteroid.updateAll()
        Particle.updateAll()
        checkCollisions()
        clscolor()
    Case STATE_GAME_OVER
        Asteroid.updateAll()
        Particle.updateAll()   
        If KeyHit(KEY_SPACE)
           setState(STATE_TITLE)
            reset()
        Endif
    End Select

    Return 0
End Method

Method OnRender:Int()
    Select gameState
    Case STATE_TITLE
    Cls 0, 0, 0
    Asteroid.drawAll()
    DrawText ("ASTEROIDS - MONKEY STYLE!", SCREEN_WIDTH2, SCREEN_HEIGHT2, 0.5, 0.5)
    DrawText ("BEST SCORE: "+Self.bestScore, SCREEN_WIDTH2, SCREEN_HEIGHT2 + 30, 0.5, 0.5)
    DrawText ("PRESS <space> TO PLAY", SCREEN_WIDTH2, SCREEN_HEIGHT2 + 60, 0.5, 0.5)
    Case STATE_GAME 
    Cls cr, cg, cb
    player.draw()
    Bullet.drawAll()
    Asteroid.drawAll()
    Particle.drawAll()
    drawHUD()
    Case STATE_GAME_OVER
    Cls 0, 0, 0
    Asteroid.drawAll()
    Particle.drawAll()
    DrawText ("GAME OVER!", SCREEN_WIDTH2, SCREEN_HEIGHT2, 0.5, 0.5)
    DrawText ("SCORE: "+score, SCREEN_WIDTH2, SCREEN_HEIGHT2 + 30, 0.5, 0.5)
    DrawText ("BEST SCORE: "+Self.bestScore, SCREEN_WIDTH2, SCREEN_HEIGHT2 + 60, 0.5, 0.5)
    DrawText ("PRESS <space> TO RETURN TO THE TITLE SCREEN", SCREEN_WIDTH2, SCREEN_HEIGHT2 + 90, 0.5, 0.5)
    End Select
    Return 0
End Method

Method setState:Void(state:Int)
    gameState = state
End

Method clscolor:Void()
    If cr > 0
    cr-=2*dt.delta
    Else
    cr = 0
    Endif
End Method

Method reset:Void()
    Bullet.list.Clear()
    Asteroid.list.Clear()
    Particle.list.Clear()
    cg = 0
    cr = 0
    cb = 0
    level = 1
    ASTEROIDS_NUM = 6
    ASTEROIDS_SIZE = 4
    score = 0
    player = New Player(SCREEN_WIDTH2, SCREEN_HEIGHT2)
    fillAsteroids(ASTEROIDS_NUM, ASTEROIDS_SIZE)   
End Method

Method checkCollisions:Void()
    For Local a:Asteroid = Eachin Asteroid.list

        If dist(player.x, player.y, a.x, a.y) <= a.avgrad
        If cr = 0 Then cr = Rnd(100, 155)
        player.shield-=2
        Endif

        For Local b:Bullet = Eachin Bullet.list 
            If a <> Null Then
                If dist(b.x, b.y, a.x, a.y) <= a.avgrad
                    a.life = a.life - 1
                    b.life = 0
                    For Local t%=1 To 4
                        New Particle(a.x, a.y, Rnd(-8,8), Rnd(-8,8), 0.95, 30, PDM_spark, 255, 192, 64, 16)
                    Next
                    For Local t%=1 To 4
                        New Particle(a.x, a.y, Rnd(-4,4), Rnd(-4,4), 0.95, 60, PDM_smlparticle, 160, 160, 160, 0)
                    Next
                Endif
                If a.life <= 0

                For Local t%=1 To 8
                    New Particle(a.x,a.y,Rnd(-10,10),Rnd(-10,10),0.95,30,PDM_spark,255,192,64,64)
                Next
                For Local t%=1 To 6
                    New Particle(a.x,a.y,Rnd(-6,6),Rnd(-6,6),0.95,30,PDM_medparticle,255,192,64,128)
                Next
                For Local t%=1 To 6
                    New Particle(a.x,a.y,Rnd(-8,8),Rnd(-8,8),0.99,60,PDM_smlparticle,160,160,160,0)
                Next
                For Local t%=1 To 5
                    New Particle(a.x,a.y,Rnd(-6,6),Rnd(-6,6),0.99,60,PDM_medparticle,160,160,160,0)
                Next
                For Local t%=1 To 4
                    New Particle(a.x,a.y,Rnd(-4,4),Rnd(-4,4),0.99,60,PDM_bigparticle,160,160,160,0)
                Next

                If a.size > 1
                    For Local t% = 1 To 2
                        New Asteroid(a.x, a.y, Rnd(-5,5), Rnd(-5,5), a.size-1)
                    Next
                Endif
                Asteroid.list.Remove(a)
                a = Null
                score+=5
                Endif
            Endif
        Next
    Next
    If Asteroid.list.Count() = 0
        level+=1
        ASTEROIDS_SIZE+=1
        ASTEROIDS_NUM+=1
        fillAsteroids(ASTEROIDS_NUM, ASTEROIDS_SIZE)
    Endif
End Method

    Method drawHUD:Void()
        DrawText ("LEVEL: "+level, 0, 0)
        DrawText("SCORE: "+score, SCREEN_WIDTH, 0, 1, 0)

        FPSCounter.draw(SCREEN_WIDTH,SCREEN_HEIGHT, 1, 1)
    End Method

    Method fillAsteroids:Void(num%, size%)
        Local tx#
        Local ty#
        For Local t% = 1 To num
            Repeat
                tx=Rnd(640)
                ty=Rnd(480)
            Until ( tx<280 or="" tx="">360 ) And ( ty<200 or="" ty="">280 )
            New Asteroid(tx, ty, Rnd(-3,3), Rnd(-3,3), size+Rnd(1))
        Next
    End Method
End Class

Class Sprite
    Field xv# ,yv#
    Field x#, y# 
    Field rotation#
End Class

Class Player Extends Sprite
    Field angVel#
    Field velmul#
    Field vel#
    Field acc#
    Field drag#
    'Field xv#,yv#
    Field xa#,ya#
    Field firedel#

    Field ship_angvel#
    Field ship_acc#
    Field ship_velmul#
    Field ship_firedel#

    Field shield#=100

    Method New(x#, y#)
        Self.x = x
        Self.y = y
        ship_angvel = 6
        ship_acc = 0.16
        ship_velmul = -0.0005
        ship_firedel = 4
        shield = 100
    End Method

    Method Update:Void()

        If KeyDown(KEY_UP)
            acc =  ship_acc
            drag = vel * ship_velmul
        Else If KeyDown(KEY_DOWN)
            drag = vel * ship_velmul * 50
        Else
            acc = 0
            drag = 0
        End If 
        If KeyDown(KEY_LEFT)
            rotation+=ship_angvel * dt.delta
        End If
        If KeyDown(KEY_RIGHT)
            rotation-=ship_angvel * dt.delta
        End If

        If KeyDown(KEY_SPACE) And Self.firedel<=0
            Local tang#=Rnd(-4,4)
            New Bullet(x - (Sin(rotation)*8), y-(Cos(rotation)*8), xv - (Sin(rotation + tang ) *12), yv-(Cos(rotation + tang ) *12), 45, 255-Rnd(4), 192+Rnd(-4,4), 64+Rnd(4,4))
            firedel = ship_firedel
        Endif
        firedel-=dt.delta

        xa = (drag * xv) - (Sin(rotation) * acc)
        ya = (drag * yv) - (Cos(rotation) * acc)
        xv = xv + xa *dt.delta
        yv = yv + ya * dt.delta
        x = x + xv * dt.delta
        y = y + yv * dt.delta
        vel = dist(0, 0, xv, yv)
        '   
        If x < 0 x = SCREEN_WIDTH
        If x > SCREEN_WIDTH x = 0
        If y < 0 y = SCREEN_HEIGHT
        If y > SCREEN_HEIGHT y = 0

        If shield <= 0
        For Local t%=1 To 18
            New Particle( x, y,Rnd(-10,10),Rnd(-10,10),0.95,130,PDM_spark,255,192,64,64)
        Next
        For Local t%=1 To 16
            New Particle( x, y,Rnd(-6,6),Rnd(-6,6),0.95,130,PDM_medparticle,255,192,64,128)
        Next
        For Local t%=1 To 16
            New Particle( x, y,Rnd(-8,8),Rnd(-8,8),0.99,160,PDM_smlparticle,160,160,160,0)
        Next
        For Local t%=1 To 15
            New Particle( x, y,Rnd(-6,6),Rnd(-6,6),0.99,160,PDM_medparticle,160,160,160,0)
        Next
        For Local t%=1 To 14
            New Particle( x, y,Rnd(-4,4),Rnd(-4,4),0.99,160,PDM_bigparticle,160,160,160,0)
        Next

        If game.score>game.bestScore
            game.bestScore = game.score
        Endif

        game.setState(STATE_GAME_OVER)
        Endif
    End Method

    Method draw:Void()
        Local x1# = x-(Sin(rotation) * 10)
        Local y1# = y-(Cos(rotation) * 10)
        Local x2# = x-(Sin(rotation + 140 ) * 8)
        Local y2# = y-(Cos(rotation + 140 ) * 8)
        Local x3# = x-(Sin(rotation - 140 ) * 8)
        Local y3# = y-(Cos(rotation - 140 ) * 8)
        SetColor 255, 255, 255
        DrawLine x1, y1, x2, y2
        DrawLine x2, y2, x3, y3
        DrawLine x3, y3, x1, y1

        SetAlpha 0.5
        If shield < 50 Then SetColor 255,0,0
        DrawRect 10,SCREEN_HEIGHT - 15, Self.shield, 10
        SetAlpha 1
        SetColor 255,0,0
    End Method

End Class

Class Bullet Extends Sprite
    Global list:List<bullet> = New List<bullet>

    Field life#
    Field cr%, cg%, cb%

    Method New(x#,y#,xv#,yv#,life#,cr%,cg%,cb%)
        Self.x = x
        Self.y = y
        Self.xv = xv
        Self.yv = yv
        Self.life = life
        Self.cr = cr
        Self.cg = cg
        Self.cb = cb

        list.AddLast Self
    End Method

    Function updateAll:Void()
        If Not list Return
        For Local b:Bullet = Eachin list
            b.update()
            If b.life < 0
                Bullet.list.Remove(b)
            b = Null
        Endif

        Next
    End Function

    Method update:Void()
        x = x + xv * dt.delta
        y = y + yv * dt.delta

        life-=dt.delta
        If x < 0 x = SCREEN_WIDTH
        If x > SCREEN_WIDTH x = 0
        If y < 0 y = SCREEN_HEIGHT
        If y > SCREEN_HEIGHT y = 0
    End Method

    Function drawAll:Void()
        If Not list Return
        For Local b:Bullet = Eachin list
            b.draw()
        Next   
    End Function

    Method draw:Void()
    Local tmul#
    If life <= 15.0
    tmul = life / 15.0
    Else
    tmul = 1.0
    Endif
    SetColor cr*tmul, cg*tmul, cb*tmul
    DrawLine x, y, x + xv, y + yv
    End Method
End Class

Class Asteroid Extends Sprite
    Global list:List<asteroid> = New List<asteroid>

    Field ang#,angvel#
    Field rad#[9]
    Field avgrad#
    Field size%
    Field life%
    Field cr%, cg%, cb% 

    Method New(x#,y#,xv#,yv#,size%)
        Self.x =x 
        Self.y =y 
        Self.xv =xv 
        Self.yv =yv 
        Self.ang =Rnd(360)
        Self.angvel =Rnd(-6,6)
        Self.size=size
        Self.life=size
        Local tcol% = Rnd(-48,48)
        Self.cr=128+tcol
        Self.cg=128+tcol
        Self.cb=128+tcol
        ' Create "Rockiness"
        Self.avgrad =0
        For Local t% = 0 To 7
            Self.rad [t]=size*8.0+Rnd(-size*4.0,size*4.0)
            Self.avgrad =Self.avgrad +Self.rad[t]
        Next
        Self.avgrad =Self.avgrad /6.0
        Self.rad[8] = Self.rad[0]

        list.AddLast Self
    End Method

    Function drawAll:Void()
        If Not list Return
            For Local b:Asteroid = Eachin list
            b.draw()
        Next   
    End Function

    Function updateAll:Void()
        If Not list Return
            For Local b:Asteroid = Eachin list
            b.update() 
        Next
    End Function

    Method update:Void()
        Self.x =Self.x +Self.xv * dt.delta 
        Self.y =Self.y +Self.yv * dt.delta 
        Self.rotation =Self.rotation +Self.angvel * dt.delta 

        If Self.x <-Self.avgrad  Then Self.x =Self.x + SCREEN_WIDTH + Self.avgrad *2
        If Self.x >SCREEN_WIDTH+Self.avgrad  Then Self.x =Self.x - SCREEN_WIDTH - Self.avgrad *2
        If Self.y <-Self.avgrad  Then Self.y =Self.y + SCREEN_HEIGHT + Self.avgrad *2
        If Self.y >SCREEN_HEIGHT+Self.avgrad  Then Self.y =Self.y - SCREEN_HEIGHT - Self.avgrad *2
    End Method

    Method draw:Void()
        Local tmul# = 360.0 / 8.0
        SetColor cr, cg, cb
        For Local t% = 0 To 7
            DrawLine x-(Sin(rotation+(t)*tmul)*rad[t]),y-(Cos(rotation+(t)*tmul)*rad[t]),x-(Sin(rotation+(t+1)*tmul)*rad[t+1]),y-(Cos(rotation+(t+1)*tmul)*rad[t+1])
        Next
    End Method
End Class

Class Particle Extends Sprite
    Global list:List<particle> = New List<particle>

    Field vm#
    Field life#,mlife#
    Field drawmode%
    Field cr%,cg%,cb%
    Field cflash%

    Method New(x#,y#,xv#,yv#,vm#,life#,drawmode%,cr%,cg%,cb%,cflash%)
        Self.x=x
        Self.y=y
        Self.xv=xv
        Self.yv=yv
        Self.vm=vm
        Self.life=life
        Self.mlife=life
        Self.drawmode=drawmode
        Self.cr=cr
        Self.cg=cg
        Self.cb=cb
        Self.cflash=cflash

        list.AddLast Self
    End Method

    Function updateAll:Void()
        If Not list Return
        For Local b:Particle = Eachin list
            b.update() 
        Next
    End Function

    Function drawAll:Void()
        If Not list Return
        For Local b:Particle = Eachin list
            b.draw()
        Next   
        End Function

    Method update:Void()
        Self.x =Self.x +Self.xv *dt.delta
        Self.y =Self.y +Self.yv *dt.delta
        Self.xv =Self.xv *(1.0-(1.0-Self.vm )*dt.delta )
        Self.yv =Self.yv *(1.0-(1.0-Self.vm )*dt.delta )
        Self.life =Self.life -dt.delta
        If Self.life <0 then="" selflife="0" if="" listremoveself="" endif="" end="" method="" draw:void="" local="" tmul="Self.life" selfmlife="" tfls="Rnd(-Self.cflash,Self.cflash)" setcolor="" limit="" selfcrtmul="" tfls0255limit="" selfcgtmul="" selfcb="" tmultfls0255="" select="" selfdrawmode="" case="" pdm_smlparticle="" drawrect="" selfx="" selfy="" 1="" pdm_medparticle="" drawoval="" -1selfy="" -133="" pdm_bigparticle="" -2selfy="" -255="" pdm_spark="" drawline="" selfxv="" selfyv="" class="" fpscounter="" abstract="" global="" fpscount:int="" starttime:int="" totalfps:int="" function="" update:void="" millisecs="" -="" starttime="">= 1000
            totalFPS = fpsCount
            fpsCount = 0
            startTime = Millisecs()
        Else
            fpsCount+=1
        Endif
    End Function

    Function draw:Void(x% = 0, y% = 0, ax# = 0, ay# = 0)
        DrawText("FPS: " + totalFPS, x, y, ax, ay)
    End Function
End Class

' From James Boyd
Class DeltaTimer
    Field targetfps:Float = 60
    Field currentticks:Float
    Field lastticks:Float
    Field frametime:Float
    Field delta:Float

    Method New (fps:Float)
        targetfps = fps
        lastticks = Millisecs()
    End

    Method UpdateDelta:Void()
        currentticks = Millisecs()
        frametime = currentticks - lastticks
        delta = frametime / (1000.0 / targetfps)
        lastticks = currentticks
    End
End

Function dist#(x1#,y1#,x2#,y2#)
    Return Sqrt(Pow((x1-x2),2) + Pow((y1-y2),2))
End Function

Function limit#(value#,low#,high#)
    If value < low Then Return low
    If value > high Then Return high
    Return value
End Function
</particle></particle></asteroid></asteroid></bullet></bullet></space></space>