File: Examples/Example_BouncingBall.html

Recommend this page to a friend!
  Classes of Emmanuel Podvin   jQuery FSM   Examples/Example_BouncingBall.html   Download  
File: Examples/Example_BouncingBall.html
Role: Example script
Content type: text/plain
Description: Example
Class: jQuery FSM
Animate page elements using Finite State Machines
Author: By
Last change: update to jquery 3.7.1
Date: 5 months ago
Size: 10,029 bytes
 

Contents

Class file image Download
<!DOCTYPE html> <html> <head> <title>iFSM in action! Bouncing Balls... </title> <meta charset="utf-8"> <script type="text/javascript" src="../extlib/jquery.min.js"></script> <script type="text/javascript" src="../extlib/jquery.dorequesttimeout.js"></script> <script type="text/javascript" src="../extlib/jquery.attrchange.js"></script> <script type="text/javascript" src="../extlib/jcanvas.min.js"></script> <script type="text/javascript" src="../iFSM.js"></script> <style type="text/css"> html { font-family: Helvetica, Arial, sans-serif; } body { padding: 0 20px; } button { margin: 0 2px; font-size: 20px; border: 1px solid #333; width: 100px; text-shadow: 0 -1px 0 #333; border-radius: 5px; } pre { font-size: 12px; background-color: black; color: green; } </style> <script type="text/javascript"> var aGameObject = { WaitProcess: { doProcess: { next_state:'Processing', }, }, Processing: { enterState: { init_function:function(){ if (this.opts.process) this.opts.process(this); }, next_state:'WaitDraw', }, }, WaitDraw: { doDraw: { init_function:function(p,e,data){ this.opts.alertSenderData=data; }, next_state:'Drawing', }, }, Drawing: { enterState: { init_function:function(){ if (this.opts.draw) this.opts.draw(this); if (this.opts.alertSenderData.aEvent) this.opts.alertSenderData.aFSM.trigger(this.opts.alertSenderData.aEvent); }, next_state:'WaitProcess', }, }, DefaultState : { start: { next_state: 'WaitProcess', }, click: { init_function:function(){ alert('object clicked!'); } }, mousemove: { init_function:function(p,e,layer){ $('#status').html('object over: '+layer.eventX+'/'+layer.eventY); } }, } }; var aGameRound = { WaitStart: { enterState: { init_function:function() { this._stateDefinition['NextRound']['doNextRound']['how_process_event'] = {delay: this.opts.speedOfGame}; this.opts.nbFSMObjects = this.opts.gameFSMObjects.length; this.opts.counterIteration =0; this.trigger('displayGame'); } }, StartStop: { next_state:'PlayGame', init_function:function(){ this.opts.lastcounterIteration=0; this.trigger('displayFPS'); } }, displayFPS:'restartDisplayFPS', restartDisplayFPS: { }, click: { init_function:function(){ alert('canvas clicked!'); } } }, PlayGame: { enterState: { init_function:function(){ this.trigger('displayGame'); }, next_state:'WaitEndProcessing', }, }, WaitEndProcessing: { EndDoDraw: { next_state_when:'this.EventIteration>=this.opts.nbFSMObjects', next_state:'NextRound', }, }, NextRound: { enterState: { propagate_event:'doNextRound', }, doNextRound: { how_process_event:{delay:10}, next_state:'PlayGame', }, }, DefaultState : { start: { next_state: 'WaitStart', }, StartStop: { next_state:'WaitStart', }, displayFPS: { how_process_event:{delay:1000}, init_function:function(){ var aCount=this.opts.counterIteration-this.opts.lastcounterIteration; this.opts.FPSCounter.html(aCount); this.opts.lastcounterIteration=this.opts.counterIteration; this.trigger('restartDisplayFPS'); } }, displayGame: { init_function:function(){ //this.myUIObject.clearCanvas(); var myFSM=this; $.each(this.opts.gameFSMObjects,function(index,aFsmGame){ aFsmGame.trigger('doProcess'); aFsmGame.trigger('doDraw',{aFSM:myFSM,aEvent:'EndDoDraw'}); }); this.opts.counterIteration++; this.opts.counter.html(this.opts.counterIteration); }, }, restartDisplayFPS: { propagate_event:'displayFPS', }, mousemove: { init_function:function(p,anEvent){ $('#status').html('mouse position: '+anEvent.offsetX+'/'+anEvent.offsetY); } } } }; /** * @param BasicStatesUI * handles simple click event, that should be transfered 'toWho' with the 'sendWhat' event sent * it is configured with its option parameters: * @param toWho: a iFSM machine * @param sendWhat: an event name * @example $('#OkConnectionButton').iFSM(BasicStatesUI,{onClic:{toWho:ClicClacMachine,sendWhat:'okDoConnection'}}); */ var BasicStatesUI = { Displayed: { enterState: { init_function: function(parameters, event, data) { this.myUIObject.show(); } } }, Hidden: { enterState: { init_function: function(parameters, event, data) { this.myUIObject.hide(); } }, }, DefaultState: { click: { init_function: function(parameters, event, data) { this.opts.onClick.toWho.trigger(this.opts.onClick.sendWhat); } }, show: { next_state: 'Displayed' }, hide: { next_state: 'Hidden' }, start: { process_event_if: 'this.opts.startState != undefined', init_function: function(parameters, event, data) { this.currentState = this.opts.startState; }, propagate_event_on_refused:'defaultState', }, defaultState: { next_state:'Displayed', } }, } $(document).ready(function() { aBackGroundGame = $('#aBackground').iFSM(aGameObject,{ canvas:$('#canvas'), color: '#FAF7F8', width: 400, height: 300, process:null, draw:function(aFSM){ aFSM.opts.canvas.drawRect({ fillStyle: aFSM.opts.color, x: 0, y: 0, width: aFSM.opts.width, height: aFSM.opts.height, fromCenter: false, });}, }); function doProcessBall(aFSM){ if (aFSM.opts.x + aFSM.opts.dx > aFSM.opts.widthScreen || aFSM.opts.x + aFSM.opts.dx < 0) aFSM.opts.dx = -aFSM.opts.dx; if (aFSM.opts.y + aFSM.opts.dy > aFSM.opts.heightScreen || aFSM.opts.y + aFSM.opts.dy < 0) aFSM.opts.dy = -aFSM.opts.dy; aFSM.opts.x += aFSM.opts.dx; aFSM.opts.y += aFSM.opts.dy; }; function doDrawBall(aFSM){ aFSM.opts.canvas.drawEllipse({ fillStyle: aFSM.opts.color, x: aFSM.opts.x, y: aFSM.opts.y, width: aFSM.opts.width, height: aFSM.opts.height, }); }; aBallGame = $('#aBall').iFSM(aGameObject,{ canvas:$('#canvas'), color: '#770000', width: 20, height: 20, widthScreen:400, heightScreen:300, x:0, y:0, dx:4, dy:8, process:doProcessBall, draw:doDrawBall, }); a2ndBallGame = $('#aSecondBall').iFSM(aGameObject,{ canvas:$('#canvas'), color: '#007777', width: 30, height: 30, widthScreen:400, heightScreen:300, x:50, y:50, dx:3, dy:6, process:doProcessBall, draw:doDrawBall, }); a3rdBallGame = $('#aThirdBall').iFSM(aGameObject,{ canvas:$('#canvas'), color: '#007700', width: 10, height: 10, widthScreen:400, heightScreen:300, x:250, y:250, dx:2, dy:5, process:doProcessBall, draw:doDrawBall, }); var aObjectList=[aBackGroundGame,aBallGame,a2ndBallGame,a3rdBallGame]; aGameFSM = $('#canvas').iFSM(aGameRound,{ gameFSMObjects:aObjectList, y:300, dx:2, dy:4, WIDTH:400, HEIGHT:300, counter:$('#counter'), FPSCounter:$('#FPSCounter'), speedOfGame:20, }); $('#StartStop').iFSM(BasicStatesUI,{onClick:{toWho:aGameFSM,sendWhat:'StartStop'}}); }); </script> </head> <body style="margin:20px;"> <h1>The bouncing ball ....</h1> <p>this example shows a game loop managed with iFsm, with bouncing balls as objects using canvas (jCanvas) to display them, using requestAnimationFrame calls instead of setTimeout</p> <section> <div> <canvas id="canvas" width="400" height="300"> This text is displayed if your browser does not support HTML5 Canvas. </canvas> <button class="onoff" id="StartStop">Start/Stop Game</button> <hr> <div>FrameCounter: <span id='counter'></span></div> <div>FPS: <span id='FPSCounter'></span></div> <div>Status: <span id='status'></span></div> <div id='aBackground'></div> <div id='aBall'></div> <div id='aSecondBall'></div> <div id='aThirdBall'></div> </div> </section> <pre> </pre> </body> </html>