|
||
| Home |
MHEG-5 Invaders ExampleThis is something I wrote for a bit of fun. It is a space invader influenced application written in MHEG-5. Don't get too excited - it's nothing like the original Space Invaders. This code demonstrates several techniques that can be applied to writing games in MHEG-5. There is a timer [5001] that moves the invaders every 250ms. Variables are used for holding the visible objects (invaders, base and missile) current position. These are modified on certain Links being fired and the visible position subsequently updated. IntegerVar 1004 and Link 4004 operate as a loop. This is achieved by the Link firing on TestEvents from the IntegerVar. To start the loop we initialise the loop counter to 0 and generate a True test event like this:
// Reset the loop counter and activate the X loop
:SetVariable ( 1004 :GInteger 0 )
:TestVariable ( 1004 1 :Ginteger 0 )
IntegerVar 1101 contains the number of times to iterate over the loop. The link Action performs the following ElementaryActions
// Increment loop counter
:Add ( 1004 1 )
...
// Repeat loop
:TestVariable ( 1004 3 :GInteger :IndirectRef 1101 )
The Link action triggers itself until all iterations have completed.
ZIP file containing MHEG text notation, ASN.1 notation and graphics:
Application
// Ian's INVADE application
//
// http://digvid.info/mheg5
//
// Copyright Ian Willis.
//
// Permission is given to distribute this code, providing citation is given
// and this copyright message is left intact.
{:Application
( '/startup' 0 ) // Application content reference
:Items (
{:Link
1
:EventSource 0 // Check this application...
:EventType IsRunning // ... for the IsRunning event
:LinkEffect (
// Load the scene
:TransitionTo (( '~/hello.mhg' 0 ) )
)
}
)
:BackgroundColour '=FF=FF=FF=00' // White
:TextCHook 10 // Default text content hook
:TextColour '=00=00=00=00' // Black
:Font "rec://font/uk1" // Font to use for text rendering
:FontAttributes "plain.26.32.0" // Default font attributes
:BitmapCHook 4 // Default bitmap content hook
}
Scene
// Ian's INVADE application
//
// http://digvid.info/mheg5
//
// Copyright Ian Willis.
//
// Permission is given to distribute this code, providing citation is given
// and this copyright message is left intact.
{:Scene
( "~/scene1.mheg" 0 )
:Items (
// Fill background with a white rectangle
{:Rectangle
10
:OrigBoxSize 720 576
:OrigPosition 0 0
:OrigLineWidth 0
:OrigRefFillColour '=ff=ff=ff=00'
}
// Top banner text
{:Text
1
:OrigContent "Ian's INVADE application (Cancel to quit)"
:OrigBoxsize 720 40
:OrigPosition 0 10
:FontAttributes "plain.24.24.0"
:HJustification centre
}
// Link for quitting scene
{:Link
2
:EventSource 0
:EventType UserInput
:EventData 16
:LinkEffect (
:quit ( ( "~/startup" 0 ) )
)
}
// Game over text
{:Text
3
:InitiallyActive False
:OrigContent "Game Over"
:OrigBoxsize 720 50
:OrigPosition 0 250
:FontAttributes "plain.36.40.0"
:HJustification centre
:VJustification centre
}
// Win/loose text
{:Text
4
:InitiallyActive False
:OrigContent "You Win"
:OrigBoxsize 720 50
:OrigPosition 0 300
:FontAttributes "plain.36.40.0"
:HJustification centre
:VJustification centre
}
// Play again text
{:Text
5
:OrigContent "Press Green to Start"
:OrigBoxsize 720 50
:OrigPosition 0 350
:FontAttributes "plain.36.40.0"
:HJustification centre
:VJustification centre
}
// Link for starting
// Some of this is not necessary the first time, but will be
// if we restart the game.
{:Link
7
:EventSource 0
:EventType UserInput
:EventData 101 // Green button
:LinkEffect (
// Hide the text boxes
:Stop ( 3 )
:Stop ( 4 )
:Stop ( 5 )
:SetData( 4 "You Win")
// Reset variables
:SetVariable ( 1001 :GInteger 50 )
:SetVariable ( 1002 :GInteger 50 )
:SetVariable ( 1003 :GInteger 10 )
:SetVariable ( 1004 :GInteger 0 )
:SetVariable ( 1006 :GObjectRef 3001)
:SetVariable ( 1007 :GInteger 0 )
:SetVariable ( 1011 :GInteger 5 )
:SetVariable ( 11001 :GInteger 20 )
// Start the invader visibles
:Run ( 3001 )
:Run ( 3002 )
:Run ( 3003 )
:Run ( 3004 )
:Run ( 3005 )
// Start the base
:SetPosition ( 13001 :IndirectRef 11001 :IndirectRef 11002 )
:Run ( 13001 )
// Activate keyboard controls
:Activate ( 14001 )
:Activate ( 14002 )
:Activate ( 14003 )
// Start the timer
:SetTimer ( 0 5001 1 )
)
}
// Invader X position
{:IntegerVar
1001
:OrigValue 50
}
// Invader Y position
{:IntegerVar
1002
:OrigValue 50
}
// Invader X delta
{:IntegerVar
1003
:OrigValue 10
}
// Invader X loop counter
{:IntegerVar
1004
:OrigValue 0
}
// Invader object reference
{:ObjectRefVar
1006
:OrigValue :ObjectRef 3001
}
// Invader X position
{:IntegerVar
1007
:OrigValue 0
}
// Temporary true if invader is alive
{:BooleanVar
1010
:OrigValue False
}
// Number of invaders
{:IntegerVar
1011
:OrigValue 5
}
// Base X position
{:IntegerVar
11001
:OrigValue 20
}
// CONSTANTS
// Number of invader columns
{:IntegerVar
1101
:OrigValue 5
}
// Invader min X position
{:IntegerVar
1102
:OrigValue 50
}
// Invader X spacing
{:IntegerVar
1103
:OrigValue 70
}
// Invader max X position
{:IntegerVar
1104
:OrigValue 350
}
// Invader Y step size (also missile step size)
{:IntegerVar
1105
:OrigValue 80
}
// Constant TRUE
{:BooleanVar
1106
:OrigValue True
}
// Invader Max Y
{:IntegerVar
1107
:OrigValue 350
}
// Constant TRUE for moving invaders
{:BooleanVar
1108
:OrigValue True
}
// Base Y position
{:IntegerVar
11002
:OrigValue 400
}
// Invader visibles
{:Bitmap
3001
:OrigContent :ContentRef ( "~/inv1.png" )
:OrigBoxsize 50 50
:OrigPosition 50 50
}
{:Bitmap
3002
:OrigContent :ContentRef ( "~/inv1.png" )
:OrigBoxsize 50 50
:OrigPosition 120 50
}
{:Bitmap
3003
:OrigContent :ContentRef ( "~/inv1.png" )
:OrigBoxsize 50 50
:OrigPosition 190 50
}
{:Bitmap
3004
:OrigContent :ContentRef ( "~/inv1.png" )
:OrigBoxsize 50 50
:OrigPosition 260 50
}
{:Bitmap
3005
:OrigContent :ContentRef ( "~/inv1.png" )
:OrigBoxsize 50 50
:OrigPosition 330 50
}
// Main invader timer actions
{:Link
4001
:EventSource 0
:EventType TimerFired
:EventData 5001
:LinkEffect (
// Reset the timer
:SetTimer (0 5001 250)
// Stop any explosion
:Stop ( 23002 )
// Increment/decrement the invader X position
:Add ( 1001 :IndirectRef 1003 )
// Test for min X position
:TestVariable ( 1001 4 :GInteger :IndirectRef 1102 )
// Test for max X position
:TestVariable ( 1001 6 :GInteger :IndirectRef 1104 )
// Copy invader X position
:SetVariable ( 1007 :GInteger :IndirectRef 1001 )
// Reset the loop counter and activate the X loop
:SetVariable ( 1004 :GInteger 0 )
:TestVariable ( 1004 1 :Ginteger 0 )
// Test whether missile is visible
:TestVariable ( 21006 1 :GBoolean True )
)
}
// Activated when invaders reach either side of the screen
{:Link
4002
:EventSource 1001
:EventType TestEvent
:EventData True
:LinkEffect (
// Reverse direction
:Multiply ( 1003 -1 )
// Move invaders down the screen
:Add ( 1002 :IndirectRef 1105 )
:TestVariable ( 1002 6 :GInteger :IndirectRef 1107 )
)
}
// Actioned when invaders reach bottom of screen
{:Link
4003
:EventSource 1002
:EventType TestEvent
:EventData True
:LinkEffect (
// Set invader count to 0 and test it
:SetData( 4 "You Loose" )
:SetVariable ( 1011 :GInteger 0 )
:TestVariable ( 1011 1 :GInteger 0 )
)
}
// Invader X loop
{:Link
4004
:EventSource 1004
:EventType TestEvent
:EventData True
:LinkEffect (
// Increment loop counter
:Add ( 1004 1 )
// Set ObjRef to correct object
:TestVariable (1106 1 :GBoolean True )
// See if this invader is still alive
:GetRunningStatus ( :IndirectRef 1006 1010 )
:TestVariable ( 1010 1 :GBoolean True )
// Increment X position of next invader
:Add (1007 :IndirectRef 1103 )
// Repeat loop
:TestVariable ( 1004 3 :GInteger :IndirectRef 1101 )
)
}
// Actioned when no invaders left
{:Link
4005
:EventSource 1011
:EventType TestEvent
:EventData True
:LinkEffect (
// Kill the timer
:SetTimer (0 5001)
// Stop game visibles
:Stop ( 3001 )
:Stop ( 3002 )
:Stop ( 3003 )
:Stop ( 3004 )
:Stop ( 3005 )
:Stop ( 13001 )
:Stop ( 23002 )
// Deactivate keyboard controls
:Deactivate ( 14001 )
:Deactivate ( 14002 )
:Deactivate ( 14003 )
// Display game over
:Run ( 3 )
// Display won/lost
:Run ( 4 )
// Display play again
:Run ( 5 )
// Activate play again link
:Activate ( 7 )
)
}
// Actioned on each alive invader
// ObjectRef is in 1006
// X position is in 1007
// Y position is in 1002
{:Link
4006
:EventSource 1010
:EventType TestEvent
:EventData True
:LinkEffect (
// Test for a missile hit
:TestVariable ( 21001 6 :GInteger :IndirectRef 1007 )
// Move this invader
:SetPosition ( :IndirectRef 1006 :IndirectRef 1007 :IndirectRef 1002 )
)
}
// Select invader 1 visible
{:Link
4101
:InitiallyActive True
:EventSource 1106
:EventType TestEvent
:EventData True
:LinkEffect (
:SetVariable (1006 :GObjectRef 3001)
:Activate ( 4102 )
:Deactivate ( 4101 )
)
}
// Select invader 2 visible
{:Link
4102
:InitiallyActive False
:EventSource 1106
:EventType TestEvent
:EventData True
:LinkEffect (
:SetVariable (1006 :GObjectRef 3002)
:Activate ( 4103 )
:Deactivate ( 4102 )
)
}
// Select invader 3 visible
{:Link
4103
:InitiallyActive False
:EventSource 1106
:EventType TestEvent
:EventData True
:LinkEffect (
:SetVariable (1006 :GObjectRef 3003)
:Activate ( 4104 )
:Deactivate ( 4103 )
)
}
// Select invader 4 visible
{:Link
4104
:InitiallyActive False
:EventSource 1106
:EventType TestEvent
:EventData True
:LinkEffect (
:SetVariable (1006 :GObjectRef 3004)
:Activate ( 4105 )
:Deactivate ( 4104 )
)
}
// Select invader 5 visible
{:Link
4105
:InitiallyActive False
:EventSource 1106
:EventType TestEvent
:EventData True
:LinkEffect (
:SetVariable (1006 :GObjectRef 3005)
:Activate ( 4101 )
:Deactivate ( 4105 )
)
}
//////////////////////////////////////////////////////////////////////////////
{:Bitmap
13001
:OrigContent :ContentRef ( "~/base.png" )
:OrigBoxsize 50 30
:OrigPosition 20 400
}
// Left keypress
{:Link
14001
:EventSource 0
:EventType UserInput
:EventData 3
:LinkEffect (
:Subtract ( 11001 20 )
:SetPosition ( 13001 :IndirectRef 11001 :IndirectRef 11002 )
)
}
// Right keypress
{:Link
14002
:EventSource 0
:EventType UserInput
:EventData 4
:LinkEffect (
:Add ( 11001 20 )
:SetPosition ( 13001 :IndirectRef 11001 :IndirectRef 11002 )
)
}
// Up keypress
{:Link
14003
:EventSource 0
:EventType UserInput
:EventData 1
:LinkEffect (
:Deactivate ( 24004 )
:SetVariable ( 21006 :GBoolean True )
:SetVariable ( 21001 :GInteger :IndirectRef 11001 )
:Add ( 21001 20 )
:SetVariable ( 21002 :GInteger 360 )
:SetPosition ( 23001 :IndirectRef 21001 :IndirectRef 21002 )
:Run ( 23001 )
:SetPosition ( 23001 :IndirectRef 21001 :IndirectRef 21002 )
)
}
// Missile X pos
{:IntegerVar
21001
:OrigValue 250
}
// Missile Y pos
{:IntegerVar
21002
:OrigValue 360
}
// Temporary comparison variable
{:IntegerVar
21003
:OrigValue 0
}
// Boolean true if missile is visible
{:BooleanVar
21006
:OrigValue False
}
// Missile visible
{:Bitmap
23001
:InitiallyActive false
:OrigContent :ContentRef ( "~/missile.png" )
:OrigBoxsize 10 30
:OrigPosition 100 400
}
// Explosion visible
{:Bitmap
23002
:InitiallyActive false
:OrigContent :ContentRef ( "~/explode.png" )
:OrigBoxsize 50 50
:OrigPosition 100 400
}
// Link fired by timer if missile is visible
{:Link
24001
:EventSource 21006
:EventType TestEvent
:EventData True
:LinkEffect (
// Move Missile
:Subtract ( 21002 20 )
:SetPosition ( 23001 :IndirectRef 21001 :IndirectRef 21002 )
// Test for missile Y position = invader y position. Activate
// 24004 if true.
:SetVariable ( 21003 :GInteger :IndirectRef 1002 )
:Add ( 21003 10 )
:Deactivate ( 24004 )
:Activate ( 24002 )
:TestVariable ( 21002 1 :GInteger :IndirectRef 21003 )
:Add ( 21003 20 )
:TestVariable ( 21002 1 :GInteger :IndirectRef 21003 )
:Deactivate (24002)
// Test for missile off top of screen
:Activate (24003)
:TestVariable ( 21002 4 :GInteger 0 )
:Deactivate (24003)
)
}
// Actioned when missile reaches invader Y position
{:Link
24002
:InitiallyActive False
:EventSource 21002
:EventType TestEvent
:EventData True
:LinkEffect (
:Activate (24004)
)
}
// Actioned when missile reaches top of screen
{:Link
24003
:InitiallyActive False
:EventSource 21002
:EventType TestEvent
:EventData True
:LinkEffect (
:Stop ( 23001 )
:SetVariable (21006 :GBoolean False )
:Deactivate (24004)
)
}
// Actioned when missile X > invader X
{:Link
24004
:InitiallyActive False
:EventSource 21001
:EventType TestEvent
:EventData True
:LinkEffect (
:SetVariable ( 21003 :GInteger :IndirectRef 1007 )
:Add ( 21003 50 )
:Activate ( 24005 )
:TestVariable ( 21003 6 :GInteger :IndirectRef 21001 )
:Deactivate ( 24005 )
)
}
// A HIT!
{:Link
24005
:InitiallyActive False
:EventSource 21003
:EventType TestEvent
:EventData True
:LinkEffect (
// Stop the missile
:Stop ( 23001 )
// Stop the invader
:Stop ( :IndirectRef 1006 )
// Disable the missile
:SetVariable ( 21006 :GBoolean False )
// Disable the hit checking
:Deactivate ( 24004 )
// Display the explosion
:Run ( 23002 )
:SetPosition ( 23002 :IndirectRef 1007 :IndirectRef 1002 )
// Decrement invader counter
:Subtract ( 1011 1 )
// Test to see if no invaders left
:TestVariable ( 1011 1 :GInteger 0 )
)
}
)
:InputEventReg 4
:SceneCS 720 576
:MovingCursor True
}
ZIP file containing MHEG text notation, ASN.1 notation and graphics:
|
|
|
Digital Video HDTV Freeview |
||
|
||||||||||||||