2 Players Simple Platformer Game tutorial (2 Players Single Screen module - NESmaker 4.1.5)

dale_coop

Moderator
Staff member
Required that you installed the Two Players core and the 2players modules: http://nesmakers.com/viewtopic.php?f=41&t=2496.
Notes: In this tutorial I will go quickly through the parts you should already known (from the basics tutorial videos). I will focus on the 2 players specificities.


NEW PROJECT
Open NESmaker, start a new project ("Project > New"). Choose "Create Blank TileSet", give a name for your project GraphicAssets folder and select the "2 players Simple Platformer" module.




PLAYERS
Set your Player object (size/graphics, "persistant", "player", "health", "speed", "acceleration", action steps/animations and a bounding box).
note: for the bounding box of all objects, always keep 1 pixels free at the bottom, because the platform engine draw sprites shifted by 1 pixel.



This Player will remain the main player, refered later as "Player 1". Select it and rename it as "Player 1".
Nothing else particular here. Set it as usual.

The player 2 is, by default, the last object of the Game Objects list. Here, in your project, it's currently labeled "Effect 7". Select this object and rename it as "Player 2".



Note: if you want to use another object than this one, you can modify the "OBJ_PLAYER_2" User Constant value (in "Project Settings > User Constants"), by default the value is 15 (= the 0...15th object).

Then, set this player like you would do for a another classic Player (size/graphics, "persistant", "player", "health", "speed", "acceleration", action steps/animations and a bounding box).



MONSTERS
Create your monsters/NPCs (and monster group) as usual.


ASSETS / TILES
Create your graphic assets as usual, in "Graphic Banks > Graphic Bank 1 > Assets".
Some precisions:
- Warp To Screen tiles warp the player.
- Monster Barrier tiles prevent monster/objects to fall from a platform. Put those tiles to the extremities. The players can walk through, other objects can't.
- One Way Block tiles are used to create platforms you can jump on from under (players can go through from down to up).
- Collect tiles, when you collect all those on a screen, you complete the screen/level (like in pacman), create the Victory Object and warp to the next screen.
- Level Clear, create the Victory Object and warp to the next screen.
- Checkpoints save your progression in the game, until you loose all your lives or reboot the game.
- Locked doors are solid until you get a key. Then, it's removed and become walkable. This tile triggers the screen, so don't forget to set the screen-type value in your "Screeen Infos".
If you want to use another tile graphic when unlocked, modify the "TILE_INDEX_PRIZE_OFF" user constant value to the index of the tile from the BckCHR_XX.bmp you want to use.
If you want to use another type, for exemple, a warp tile when unlocked, modify the "COL_OPENDOOR" user constant value to "2".
- Monster locks are solid until you there is no monster on the screen.
If you want to use another tile graphic when removed, modify the "TILE_MONSTER_LOCK_OFF" user constant value to the index of the tile from the BckCHR_XX.bmp you want to use.
If you want to use another type, for exemple, a warp tile when removed, modify the "COL_MONSTER_LOCK_OFF" user constant value to "2".


SCREENS
Set your screen as usual. Define the Player 1 starting point on your main screen.



The second Player will be spawn just next to the Player 1 (not too far, to avoid collision issues. we don't want him to spawn on a solid or hole / death tile). However, you can defined the offset of the Player 2 spawn position by changing the "PLAYER_2_OFFSET_STARTING" User Constant, in "Project Settings > User Constants".
(Notes: there also another constant named "PLAYER_2_OFFSET_TRANSITIONS" that is used on screen transitions, but I'd strongly suggest to keep this one to "0", else you will have serious issues during screen transitions)

In the "Screen Infos", set the "Screen uses Gravity" flag.



Notes: The "cutscene" flag doesn't do anything, except... when this is set, the players' inputs are disabled. So if you use this flag (with maybe "hide hud") you could design some cutscene screens (I used that for my game... I didn't remove that flag).


PLAYER WEAPON
The weapon is only available when the Weapon 1 is unlocked. You can get it from a NPC. Or set it unlocked from start, via the "Project info" dialog.
By default, this module is set to use the sprite based weapon, because it uses less memory.

- Sprite Based Weapon:
The idea is a sprite (tile) is drawn next to the player, when he's in attacking state (the action step 3).
To set the Sprite Weapon tile used, opn the "Project Settings > User Constants" and modify the "SPRITE_WEAPON" value. The weapon is a not animated 8x8 tile (using the Sub 2 palette).


(By default, the tile used for the sprite weapon is the 28)

The action step (animation) used when attacking with the weapon is the action step 3.
The input script to use with will be the "b_create_weapon_sprite.asm" script (in the "Basic_NoScroll_TwoPlayers\ModuleScripts\InputScripts\SimplePlatformer\" folder).

If you need a bigger or an animated weapon... I'd suggest to switch to a Melee Object Weapon.

- Melee Object Weapon:
In order to use an object instead of a sprite for the Weapon, you need to disable the sprite based weapon first. Go to "Project Settings > User Constants" and set the "SPRITE_WEAPON" constant to "0".
By default, the object used is the Melee object (01). However, you could change for another object by modifying the "OBJECT_PLAYER_MELEE" constant.


Now, set your Melee object: "player weapon", edge/solid reaction" to "DestroyMe". Animation type if you have animations.


For the action step 0, set the "Ignore Gravity" and End Action to "DestroyMe" with a timer of "1"
And don't forget to set the bounding box.
The input script to use with will be the "b_create_melee_object.asm" script (in the "Basic_NoScroll_TwoPlayers\ModuleScripts\InputScripts\SimplePlatformer\" folder).
The action step (animation) used when attacking with the weapon is the action step 3 (defined in the script).


PLAYER WEAPON OFFSET
To set the origin position / offset, go to "Game Objects", click on the "Melee/Projectile" button to display "Melee".



And set the position for each facing direction.


PLAYER PROJECTILES
The magic/projectile is only available when the Weapon 2 is unlocked. You can get it from a NPC. Or set it unlocked from start, via the "Project info" dialog.
By default in this module, the object used is the Projectile Source object (02). However, you could change for another object by modifying the "OBJECT_PLAYER_PROJECTILE" constant.
Set the projectile object as usual (size/graphics, "player weapon", "speed", "acceleration", "Ignore Gravity" for the action step 0 and a bounding box)



The input script to use with will be the "b_create_projectile_platformer.asm" script (in the "Basic_NoScroll_TwoPlayers\ModuleScripts\InputScripts\SimplePlatformer\" folder).
The action step (animation) used when attacking with magic/projectile is the action step 3 (defined in the script).


PLAYER DEATH
When any player dies, it uses the Player Death object, by default it's the "Effect 0" object (08). It's defined by the "OBJ_PLAYER_DEATH" constant in "Project Settings > User Constants". Select this object and rename it to "Player Death".
Because both players maybe not use the same graphics/animation... each uses a different action step.
The Player 1 uses the Action Step 0 (like it works in the Basic modules) and the Player 2 the Action Step 1.
Set your Player Death:
For the Action Step 0 (corresponding to the player 1), set the "Ignore Gravity" and End Animation to "Restart Game", with a animation speed.
For the Action Step 1 (corresponding to the player 2), set the "Ignore Gravity" and End Animation to "Restart Game", with a animation speed.


And don't forget the bounding box.


PLAYER VICTORY
When the level complete/win is executed (if using a Collectable tile), this object is displayed. By default it's the "Effect 2" object (10). It's defined by the "OBJ_PLAYER_VICTORY" constant in "Project Settings > User Constants". Select this object and rename it to "Player Victory".
Like the Player Death object, the Player Victory object uses separate action steps for Player 1 and Player 2.
Set your Player Victory:
For the Action Step 0 (corresponding to the player 1), set the "Ignore Gravity" and End Animation to "GoToWarp", with a animation speed.
For the Action Step 1 (corresponding to the player 2), set the "Ignore Gravity" and End Animation to "GoToWarp", with a animation speed.


And don't forget the bounding box.


MONSTER DEATH
Set your monster death as usual. Like in the Basic modules, by default, it uses the "Effect 1" game object (09).
For the Action Step 0, set "Ignore Gravity" and End Animation to "DestroyMe", with a animation speed… And don't forget the bounding box.


MONSTER DROPS
By defaut the monster drops are disabled. If you want you monsters to drop random items when they die, in the "Project Settings > User Constants", define the "OBJ_MONSTER_DROP_ITEM1", "OBJ_MONSTER_DROP_ITEM2" and "OBJ_MONSTER_DROP_ITEM3" constants. For example, if you want your monster to drop an Health Pickup, or Charge Pickup or a Currency Pickup… just set the constants to "4", "5" and "7".
If "0" for all, no object will be drop.


MONSTER PROJECTILES
When the monster objects are set to "Shoot Forward" or "Shoot at Player", by default, it creates the Projectile object (03). It's defined by the "OBJ_MONSTER_PROJECTILE" constant in "Project Settings > User Constants".

- Shoot Forward:
The shoot forward/straight uses the Action Step 0. Set your projectile object to "Monster Weapon", give it a "Speed" and "Acceleration", edge/solid reaction" to "DestroyMe".
Set the "Ignore Gravity" for the Action Step 0.


And don't forget the bounding box.

- Shoot at Player:
The shoot at Player uses the Action Step 1. Set your projectile object to "Monster Weapon", give it a "Speed" and "Acceleration", edge/solid reaction" to "DestroyMe".
For the Action Step 1 set the "Ignore Gravity" and the "Use aimed Physics" (because shoot at player physics code is different).


And don't forget the bounding box.


TWO PLAYERS MODE
The 2 players modules can play in "1 player" mode (only the player 1, like basic modules) or in "2 players" mode.
This is defined by a User Variable named "player2Mode", in the "Project Settings > User Variables".
If the value is "0": it's 1 player only.
If the value is "1": it's 2 players.
This variable can be set via a input script "SelectionStartScreen.asm" script (in the "Basic_NoScroll_TwoPlayers\ModuleScripts\InputScripts\" folder).


START MENU / SELECTION

So, in order to be able to select the mode ( 1 player or 2 players mode), the Start Screen has a SELECTION system.
First, in the "Project Infos" dialog, uncheck the "skip Start Screen".
By default, a cursor/selector is displayed on the Start Screen. This cursor position reflects the value of the "player2Mode" variable.
The sprite used as a cursor is the tile 127 (the last 8x8 tile of the GameObjectTiles.bmp"), you can change for another one by modifying the "STARTSCREEN_CURSOR_TILE" user constant.
There are two position items, the first one is for the 1 player mode and the second for the 2 players mode.



The position of the first item, is defined by the "SELECTION_POS_X" and the "SELECTION_POS_Y" user constants, it's the pixel coord on the screen.
The input script to use with the selection will be the "SelectionStartScreen.asm" script (in the "Basic_NoScroll_TwoPlayers\ModuleScripts\InputScripts\" folder).
And the "StartGame.asm" to validate and start the game.


INPUTS SCRIPTS / INPUTS EDITOR

Now you have set all your objects, monsters, graphic assets and screens… we'll see how to assign input scripts, that is slightly different than it's in the Basic modules.

First, in the "Scripts > Input Scripts", add all the scripts we will need for our inputs:
- from the "Basic_NoScroll_TwoPlayers\ModuleScripts\MovementScripts\SimplePlatformer" folder, take all the scripts.
- from the "Basic_NoScroll_TwoPlayers\ModuleScripts\InputScripts\SimplePlatformer" folder, take the "a_simple_jump.asm", "varJump.asm", "a_create_projectile_platformer.asm" and the "b_create_weapon_sprite.asm" scripts, if you use the sprite based weapon (or the "b_create_melee_object.asm" one, if you want to use the Melee Object).
- from the "Basic_NoScroll_TwoPlayers\ModuleScripts\InputScripts" folder, take all the "SelectionStartScreen.asm", "StartGame.asm" and the "b_activate_text_box.asm" scripts.

Now, go to the "Input Editor".
All the scripts need to be assign either to the "Player 1" and/or the the "Player 2" as Target (no more NULL).
So, for example with the "StartMovingPlayerDown.asm", select "MainGame" for Game State, "Player 1" for Target, "StartMovingPlayerDown.asm" for Script to Run, "Hold" and the Down direction button. And click on "Add".
Now, set "Player 2" as Target. And click on "Add".
Your player 1 can go down. Your player 2 can go down.


Do exaclty same for all the Movement scripts… the jumps and the weapons scripts.

For the SelectionStartScreen and the GameStart scripts, I'd suggest to just assign them to the "Player 1" inputs.


Voilà, it should be ready to Export & Test.
Let's me know if something is not clear and need more informations.
 

rimoJO

New member
Thanks for the tutorial! I'm making a SSB style game with it now! Anyways, what is going on I don't get it
 

Attachments

  • w h a t   i s   t h i s.PNG
    w h a t i s t h i s.PNG
    12.7 KB · Views: 4,428

dale_coop

Moderator
Staff member
You mean your health HUD ?
Be sure to set up both myHealth1 and myHealth2 elements (initial value for the hud vars) and displayed on the hud.
 

dale_coop

Moderator
Staff member
Sure you set correctly your HUD elements?
Please share your settings, what you did, what you modified... and not only the weird result.

Looks like it's related to your HUD health. Right? Could you share that... (myHealth hud elements settings)?
 
Hey I'm having a weird problem with player projectiles in this module. The first projectile a player shoots doesn't ignore gravity and ignores all actions ( I have it set to only go a certain distance and destroy itself but the first projectile goes across the whole screen). But it's only the first projectile, the rest after that are perfectly fine? Also if the projectile touches the edge of the screen it warps the player to that screen??

Code:
; load the playerX_object (current inputs):
JSR PlayerXobjectInputs

createWeaponProjectile:
    ;; if on a cutscene:
    LDA screenFlags
    AND #%00000010
    BEQ +
    RTS
    +
    LDA isPaused
    BEQ +
    RTS
    +

    ;TXA
    ;STA playerX_object
    LDA gameHandler
    AND #%00100000  
    BEQ notNPCstate_proj
    JMP doneShooting
notNPCstate_proj:
    LDA weaponsUnlocked
    AND #%00000010
    BNE canShoot
    JMP doneShooting
canShoot:
    CountObjects #%00000100, #$00   ;; count player weapon on screen
    LDA monsterCounter              ;; the variable used to count is monsterCounter
    CLC
    CMP #$01        ;; compare to 1
    BCC +       ;; if less than 2 on screen we can create a projectile
    RTS         ;; else we quit
    +
    ;LDA limitProjectile
    ;BNE continueCreateProjectile
    ;RTS
continueCreateProjectile:
    ;LDX player1_object
    ;;; IF YOU WANT TO USE AN SPECIFIC ANIMATION / ACTION STEP WHEN SHOOTING, comment out the following 3 lines: 
    ;;; check if already shooting (assuming the shoot action step is 03)
    GetCurrentActionType playerX_object
    CMP #$03
    BNE notAlreadyShooting
    JMP doneShooting
notAlreadyShooting:
    ;;; IF YOU WANT TO USE AN SPECIFIC ANIMATION / ACTION STEP WHEN SHOOTING, comment out the following 1 line: 
    ;;; if not already shooting, change it's action step (assuming the shoot action step is 03)
    ChangeObjectState #$03, #$02
    
    ;;; if you want your player stops when he's shooting, comment out the following lines:
    LDA Object_movement,x
    AND #%00001111
    ORA #%00000010
    STA Object_movement,x
    LDA #$00
    STA Object_h_speed_hi,x
    STA Object_h_speed_lo,x
    STA Object_v_speed_hi,x
    STA Object_v_speed_lo,x
    
;; if was already shooting
wasAlreadyShooting:

    LDA Object_movement,x
    AND #%00000111
    STA temp2
    TAY

    LDA Object_x_hi,x
    SEC 
    SBC #$08 ;; width of projectile 
    STA temp

    LDA temp
    ;;; offset x for creation
    CLC
    ADC projOffsetTableX,y
    STA temp
    LDA temp3
    ADC #$00
    STA temp3

    LDA Object_y_hi,x
    CLC
    ADC projOffsetTableY,y
    sec
    sbc #$08 ;; height of projectile
    STA temp1   
    
    
    CreateObject temp, temp1, #OBJECT_PLAYER_PROJECTILE, #$00, currentNametable
    
    ;DEC limitProjectile
  
    ;;;; x is now the newly created object's x.
    LDA Object_movement,x
    ORA temp2
    STA Object_movement,x
    LDY temp2
    LDA directionTable,y
    ORA Object_movement,x
    STA Object_movement,x
    
    PlaySound #SND_SHOOT
doneShooting:
    RTS

Haven't done much to the projectile script but here it is if that helps.
 

dale_coop

Moderator
Staff member
Your projectile object is set correctly? (as "player weapon", action steps using the "ignore gravity" flag) and the "OBJECT_PLAYER_PROJECTILE" user constant value is correct (in "project settings > user constants")?
Is the Edge Reaction set DestroyMe?
Have you made any other modification in scripts? (handle left / right bounds scripts ?)...
 
Yes player weapon, ignore gravity and constant are set correctly. Usually after the first projectile it goes to normal but sometimes its after 4 or 5. No idea how it could be so random like that. And I haven't changed the bounds scripts at all.
Here's a video of what exactly is happening.
[media]https://www.youtube.com/watch?v=HUW9VLnVivM[/media]

EDIT: Also yes its set to DestroyMe on both solid and screen edge.
 

dale_coop

Moderator
Staff member
Interesting... could you share screenshots of your projectile's details? (of all the tabs)
I will try to reproduce on my demo project.
 

dale_coop

Moderator
Staff member
Ok... and have you set the Player2 object?
On the video we see only the Player1. Where is the player2... is he dead?
 
:eek: I'm so dumb. I set the player2mode to 0 and it functions with no problems at all. So it's thinking that the player2object is the projectile or something? that's very strange... could this still potentially happen if 1 of the players dies? And thanks for the help I'm dense sometimes :oops:
 

dale_coop

Moderator
Staff member
Ah ah ;)
If you set the player2mode to "0" it means the player 2 mode is disabled. So, only one player in the game... (a 1 player geame)
If player2mode is "1" it means the player 2 mode is enabled... a 2 players game. In that mode, the engine needs the second player object to be set ("player", "persistent", ... bounding box,...). Else the object will be create, but he will fall.... because no bounding box... and cause weird effects on the engine :S
 

dale_coop

Moderator
Staff member
No problem... it's not obvious... sorry to not have written it down in the tutorial ;)
btw, your game looks great!
 

rimoJO

New member
hi! i was just using the module on 4.1.0. i think that's why the hud didn't work. oh well. anyways, i noticed that there was a golden bunny and a silver bunny. How do you have multiple game object palettes?
 

dale_coop

Moderator
Staff member
On the Player object, assign another subpalette for the "Sub 2":



Note, you can only use 2 sub-palettes, the same for ALL your Game Objects.
 
Top Bottom