< Zurück

02.12.2012 22:54:00 • Categories: Monkey X, 2D Game SDK / Framework, Multiplatform • Tags: Monkey

Monkey: virtual stick

Strict
Import mojo

Class VirtualStickTestApp Extends App     Const PLAYFIELD_WIDTH:Float = 200     Const PLAYFIELD_HEIGHT:Float = 200     Const PLAYER_SPEED:Float = 5

    ' our virtual stick     Field mystick:MyStick

    ' the "player"'s location     Field playerX:Float = PLAYFIELD_WIDTH/2     Field playerY:Float = PLAYFIELD_HEIGHT/2     Field playfieldX:Float     Field playfieldY:Float = 10

    Method OnCreate:Int()         mystick = New MyStick         mystick.SetRing(100, DeviceHeight()-100, 40)         mystick.SetStick(0, 0, 15)         mystick.SetDeadZone(0.2)         mystick.SetTriggerDistance(5)         playfieldX = DeviceWidth()-PLAYFIELD_WIDTH-10         SetUpdateRate 30         Return 0     End

    Method OnUpdate:Int()         ' update the stick usage         UpdateStick()

        ' update the player position         If mystick.GetVelocity() <> 0 Then             playerX += mystick.GetDX() PLAYER_SPEED             playerY -= mystick.GetDY() PLAYER_SPEED             If playerX < 0 Then                 playerX = 0             Elseif playerX > PLAYFIELD_WIDTH Then                 playerX = PLAYFIELD_WIDTH             End             If playerY < 0 Then                 playerY = 0             Elseif playerY > PLAYFIELD_HEIGHT Then                 playerY = PLAYFIELD_HEIGHT             End         End         Return 0     End

    Method OnRender:Int()         Cls(0,0,0)

        mystick.DoRenderRing()         mystick.DoRenderStick()         DrawOutlineRect(playfieldX, playfieldY, PLAYFIELD_WIDTH, PLAYFIELD_HEIGHT)         DrawCircle(playfieldX + playerX, playfieldY + playerY, 5)

        ' some test info         DrawText("angle="+mystick.GetAngle(), 10, 10)         DrawText("vel="+mystick.GetVelocity(), 10, 30)         DrawText("dx="+mystick.GetDX(), 10, 50)         DrawText("dy="+mystick.GetDY(), 10, 70)         Return 0     End

    Method UpdateStick:Void()         If mystick.GetTouchNumber() < 0 Then             #if TARGET="android" Then                 For Local i:Int = 0 To 31                     If TouchHit(i) And mystick.GetTouchNumber() < 0 Then                         mystick.StartTouch(TouchX(i), TouchY(i), i)                     End                 End             #else                 If MouseHit(0) Then                     mystick.StartTouch(MouseX(), MouseY(), 0)                 End             #endif         End

        If mystick.GetTouchNumber() >= 0 Then             #if TARGET="android" Then                 If TouchDown(mystick.GetTouchNumber()) Then                     mystick.UpdateTouch(TouchX(mystick.GetTouchNumber()), TouchY(mystick.GetTouchNumber()))                 Else                     mystick.StopTouch()                 End             #else                 If MouseDown(0) Then                     mystick.UpdateTouch(MouseX(), MouseY())                 Else                     mystick.StopTouch()                 End             #endif         End     End End

Class MyStick Extends VirtualStick     Method RenderRing:Void(x:Float, y:Float)         SetColor 0, 0, 255         Super.RenderRing(x, y)         SetColor 255, 255, 255     End

    Method RenderStick:Void(x:Float, y:Float)         SetColor 0, 255, 0         Super.RenderStick(x, y)         SetColor 255, 255, 255     End End

Class VirtualStick Private     ' the coordinates and dimensions for the virtual stick's ring (where the user will first touch)     Field ringX:Float     Field ringY:Float     Field ringRadius:Float

    ' the coordinates and dimensions for the stick (what the user is pushing around)     ' X/Y is relative to the centre of the ring, and positive Y points up     Field stickX:Float = 0     Field stickY:Float = 0     Field stickRadius:Float     Field stickAngle:Float     Field stickPower:Float

    ' where the user first touched     Field firstTouchX:Float     Field firstTouchY:Float

    ' power must always be >= this, or we return 0     Field deadZone:Float

    ' we need to move the stick this much before it triggers     Field triggerDistance:Float = -1     Field triggered:Bool = False

    ' the index of the touch event that initiated the stick movement     Field touchNumber:Int = -1

    ' clips the stick to be within the ring, and updates angles, etc.     Method UpdateStick:Void()         If touchNumber>=0 Then             Local length:Float = Sqrt(stickXstickX+stickYstickY)             stickPower = length/ringRadius             If stickPower > 1 Then stickPower = 1

            If stickPower < deadZone Then                 stickPower = 0                 stickAngle = 0                 stickX = 0                 stickY = 0             Else                 If stickX = 0 And stickY = 0 Then                     stickAngle = 0                     stickPower = 0                 Elseif stickX = 0 And stickY > 0 Then                     stickAngle = 90                 Elseif stickX = 0 And stickY < 0 Then                     stickAngle = 270                 Elseif stickY = 0 And stickX > 0 Then                     stickAngle = 0                 Elseif stickY = 0 And stickX < 0 Then                     stickAngle = 180                 Elseif stickX > 0 And stickY > 0 Then                     stickAngle = ATan(stickY/stickX)                 Elseif stickX < 0 Then                     stickAngle = 180+ATan(stickY/stickX)                 Else                     stickAngle = 360+ATan(stickY/stickX)                 End                 If length > ringRadius Then                     stickPower = 1                     stickX = Cos(stickAngle) ringRadius                     stickY = Sin(stickAngle) ringRadius                 End             End         End     End

Public

    Method GetTouchNumber:Int()         Return touchNumber     End

    ' the angle in degrees that the user is pushing, going counter-clockwise from right     Method GetAngle:Float()         Return stickAngle     End

    ' the strength of the movement (0 means dead centre, 1 means at the edge of the ring (or past it)     Method GetVelocity:Float()         Return stickPower     End

    ' based on the angle and velocity, get the DX     Method GetDX:Float()         Return Cos(stickAngle) * stickPower     End

    ' based on the angle and velocity, get the DY     Method GetDY:Float()         Return Sin(stickAngle) * stickPower     End

    ' we just touched the screen at point (x,y), so start "controlling" if we touched inside the ring     Method StartTouch:Void(x:Float, y:Float, touchnum:Int)         If touchNumber < 0 Then             If (x-ringX)(x-ringX) + (y-ringY)(y-ringY) <= ringRadius*ringRadius Then                 touchNumber = touchnum                 firstTouchX = x                 firstTouchY = y                 triggered = False                 If triggerDistance <= 0 Then                     triggered = True                     stickX = x-ringX                     stickY = ringY-y                 End                 UpdateStick()             End         End     End

    ' a touch just moved, so we may need to update the stick     Method UpdateTouch:Void(x:Float, y:Float)         If touchNumber>=0 Then             If Not triggered Then                 If (x-firstTouchX)(x-firstTouchX)+(y-firstTouchY)(y-firstTouchY) > triggerDistance*triggerDistance Then                     triggered = True                 End             End             If triggered Then                 stickX = x - ringX                 stickY = ringY - y                 UpdateStick()             End         End     End

    ' we just released a touch, which may have been this one     Method StopTouch:Void()         If touchNumber>=0 Then             touchNumber = -1             stickX = 0             stickY = 0             stickAngle = 0             stickPower = 0             triggered = False         End     End

    Method DoRenderRing:Void()         RenderRing(ringX, ringY)     End

    Method DoRenderStick:Void()         RenderStick(ringX+stickX, ringY-stickY)     End

    ' draws the stick (may be overridden to do images, etc.)     Method RenderStick:Void(x:Float, y:Float)         DrawCircle(x, y, stickRadius)     End

    ' draws the outside ring (may be overridden to do images, etc.)     Method RenderRing:Void(x:Float, y:Float)         DrawCircle(x, y, ringRadius)     End

    ' set the location and radius of the ring     Method SetRing:Void(ringX:Float, ringY:Float, ringRadius:Float)         Self.ringX = ringX         Self.ringY = ringY         Self.ringRadius = ringRadius     End

    ' set the location and radius of the stick     Method SetStick:Void(stickX:Float, stickY:Float, stickRadius:Float)         Self.stickX = stickX         Self.stickY = stickY         Self.stickRadius = stickRadius     End

    Method SetDeadZone:Void(deadZone:Float)         Self.deadZone = deadZone     End

    Method SetTriggerDistance:Void(triggerDistance:Float)         Self.triggerDistance = triggerDistance     End End

Function Main:Int()     New VirtualStickTestApp     Return 0 End

Function DrawOutlineRect:Void(x:Float, y:Float, width:Float, height:Float)     DrawLine(x, y, x+width, y)     DrawLine(x, y, x, y+height)     DrawLine(x+width, y, x+width, y+height)     DrawLine(x, y+height, x+width, y+height) End


< Zurück | ^ nach oben