Character Behavior

Hello guys!

I wonder if Corona has something like behaviors for characters. I come from Scirra’s Construct 2 platform and it can set a character/object with a type of behavior like “car, jump-through, 8 direction, bullet, etc”.

What I mean is… is there anything that we could just say to the compiler that if player 1 receives a keyEvent from a button to walk to the right… the character would walk all the way until this button is no longer pressed… or to jump…   (skipping the physics … like we do with applyLinearImpulse).

Thanks to you all!

:slight_smile:

@henriquesv,
 
I’m not aware of any existing libraries for Corona that implement a behavior- or component- based approach.
 
That said I’m glad you’re asking this question.  I’ve been considering implementing a component.* plugin and a community accessible library of components, but I wasn’t sure if the community would dig it or not.
 
For now, until I make up my mind and then get done with the initial version of this, you have to code this kind of thing on your own.
 
My own approach to this kind of coding it to use custom events as follows:
 
First, a basic KEY listener to catch WASD events and throw custom events (just as an example).

local function key( event ) if( event.phase == "down" ) then -- the key press if(event.keyName == "w" ) then Runtime:dispatchEvent( { name = "onMove", y = -1, phase == "began" } ) elseif(event.keyName == "a" ) then Runtime:dispatchEvent( { name = "onMove", x = -1, phase == "began" } ) ... more ... elseif( event.phase == "up" ) then -- the key release if(event.keyName == "w" ) then Runtime:dispatchEvent( { name = "onMove", y = 1, phase == "ended" } ) elseif(event.keyName == "a" ) then Runtime:dispatchEvent( { name = "onMove", x = 1, phase == "began" } ) ... more ... end

 
Then, an object with a listener for the custom event ‘onMove’

local player = display.newCircle( 10, 10, 10 ) player.moveX = 0 player.moveY = 0 function player.onMove( self, event ) self.moveX = self.moveX + (event.x or 0) self.moveY = self.moveY + (event.y or 0) end; Runtime:addEventListener( "onMove", player ) function player.enterFrame( self ) self.x = self.x + self.moveX self.y = self.y + self.moveY end; Runtime:addEventListener( "enterFrame", player )

This may all seem a bit convoluted at first, and some may say… why not just attach the key listener directly to the player.
 
While you could do that, if you should later decide to change from a key-input to a touch input or a joystick input, you’d have to recode the movement logic.  If however, you separate the input from the processing, you can simply add a new input listener and Viola, you’re good go go!
 
Finally, the above example sucks!  I know, but I just wanted to demonstrate some principles while answering your question.

FYI - I already have the component.* module and some sample components written.
 
The above ‘fake’ mover would look something like this:

local c\_manager = require "scripts.components" local basicMover = require "scripts.basicMover" local obj = display.newCircle( 10, 10, 10 ) local components = { basicMover( { style = "key", xRate = 1, yRate = 1 } ), } c\_manager.attach( obj, components )

PS - I’m going back and forth between component and behavior with a preference for the latter right now.

Hi roaminggamer!

Thanks for your reply! You initiative would be awesome!

I have another doubt… how do you keep track of speed and acceleration? Is there any tick/timer related to this? Like, how often is the listeners called? Does corona provide a time delta for us to calculate speed and acceleration to move the objects?

All the best!

Working on the “setLinearVelocity” here =)

  1. ‘another doubt’ - You mean, another question.  Google translate is providing the wrong word.  

I’ve seen this a lot.  Can you tell me what language you are translating from?  Just curious.

  1. enterFrame - executes once per frame.

  2. FPS can be set to 30 or 60

  3. Thus ‘enterFrame’ can execute ‘_ approximately _’ every 33 or 16 ms respectively.  

  4. Frame period is not guaranteed and will vary a little over time.

  5. Corona does not provide a delta time.  You must measure it yourself.  SSK2does this automatically, but if this is all you need don’t use SSK2.  Simply do this:

With SSK2:

local rate = 200 -- 200 pixels per second function obj.enterFrame( self ) local dt = ssk.getDT() -- ms since last frame local moveDist = rate \* dt/1000 end

Without:

local rate = 200 -- 200 pixels per second obj.lastT = system.getTimer() function obj.enterFrame( self ) local curT = system.getTimer() local dt = curT - obj.lastT obj.lastT = curT local moveDist = rate \* dt/1000 end
  1. I don’t understand your question about tracking acceleration.  You can get the speed of a physics object with

getLinearVelocity()

  1. Please note, moving objects by setting x and y values is allowed, but not the best way.  If you want to properly move objects use physics.* forces.  

Also, please take some time to read all the physics tutorialsand guides.

Just as to a nod to RG, I too am tackling this beast and after reading what I can find on linear velocity I figured that I might just go the moveX route, it just seems easier and gives me more control.

Now if I had a nice component library I could use…  :slight_smile:

@henriquesv,
 
I’m not aware of any existing libraries for Corona that implement a behavior- or component- based approach.
 
That said I’m glad you’re asking this question.  I’ve been considering implementing a component.* plugin and a community accessible library of components, but I wasn’t sure if the community would dig it or not.
 
For now, until I make up my mind and then get done with the initial version of this, you have to code this kind of thing on your own.
 
My own approach to this kind of coding it to use custom events as follows:
 
First, a basic KEY listener to catch WASD events and throw custom events (just as an example).

local function key( event ) if( event.phase == "down" ) then -- the key press if(event.keyName == "w" ) then Runtime:dispatchEvent( { name = "onMove", y = -1, phase == "began" } ) elseif(event.keyName == "a" ) then Runtime:dispatchEvent( { name = "onMove", x = -1, phase == "began" } ) ... more ... elseif( event.phase == "up" ) then -- the key release if(event.keyName == "w" ) then Runtime:dispatchEvent( { name = "onMove", y = 1, phase == "ended" } ) elseif(event.keyName == "a" ) then Runtime:dispatchEvent( { name = "onMove", x = 1, phase == "began" } ) ... more ... end

 
Then, an object with a listener for the custom event ‘onMove’

local player = display.newCircle( 10, 10, 10 ) player.moveX = 0 player.moveY = 0 function player.onMove( self, event ) self.moveX = self.moveX + (event.x or 0) self.moveY = self.moveY + (event.y or 0) end; Runtime:addEventListener( "onMove", player ) function player.enterFrame( self ) self.x = self.x + self.moveX self.y = self.y + self.moveY end; Runtime:addEventListener( "enterFrame", player )

This may all seem a bit convoluted at first, and some may say… why not just attach the key listener directly to the player.
 
While you could do that, if you should later decide to change from a key-input to a touch input or a joystick input, you’d have to recode the movement logic.  If however, you separate the input from the processing, you can simply add a new input listener and Viola, you’re good go go!
 
Finally, the above example sucks!  I know, but I just wanted to demonstrate some principles while answering your question.

FYI - I already have the component.* module and some sample components written.
 
The above ‘fake’ mover would look something like this:

local c\_manager = require "scripts.components" local basicMover = require "scripts.basicMover" local obj = display.newCircle( 10, 10, 10 ) local components = { basicMover( { style = "key", xRate = 1, yRate = 1 } ), } c\_manager.attach( obj, components )

PS - I’m going back and forth between component and behavior with a preference for the latter right now.

Hi roaminggamer!

Thanks for your reply! You initiative would be awesome!

I have another doubt… how do you keep track of speed and acceleration? Is there any tick/timer related to this? Like, how often is the listeners called? Does corona provide a time delta for us to calculate speed and acceleration to move the objects?

All the best!

Working on the “setLinearVelocity” here =)

  1. ‘another doubt’ - You mean, another question.  Google translate is providing the wrong word.  

I’ve seen this a lot.  Can you tell me what language you are translating from?  Just curious.

  1. enterFrame - executes once per frame.

  2. FPS can be set to 30 or 60

  3. Thus ‘enterFrame’ can execute ‘_ approximately _’ every 33 or 16 ms respectively.  

  4. Frame period is not guaranteed and will vary a little over time.

  5. Corona does not provide a delta time.  You must measure it yourself.  SSK2does this automatically, but if this is all you need don’t use SSK2.  Simply do this:

With SSK2:

local rate = 200 -- 200 pixels per second function obj.enterFrame( self ) local dt = ssk.getDT() -- ms since last frame local moveDist = rate \* dt/1000 end

Without:

local rate = 200 -- 200 pixels per second obj.lastT = system.getTimer() function obj.enterFrame( self ) local curT = system.getTimer() local dt = curT - obj.lastT obj.lastT = curT local moveDist = rate \* dt/1000 end
  1. I don’t understand your question about tracking acceleration.  You can get the speed of a physics object with

getLinearVelocity()

  1. Please note, moving objects by setting x and y values is allowed, but not the best way.  If you want to properly move objects use physics.* forces.  

Also, please take some time to read all the physics tutorialsand guides.

Just as to a nod to RG, I too am tackling this beast and after reading what I can find on linear velocity I figured that I might just go the moveX route, it just seems easier and gives me more control.

Now if I had a nice component library I could use…  :slight_smile: