- Warrior is the first vector game in which Tim Skelly utilized a 16x12 grid of data which described locations on the screen. He would go on to use a similar 32 x 24 grid in Armor Attack.
- Codes used:
$01 Right Player Safe Zone
$02 Left Player Safe Zone
$07 Right Boundary
$0B Left Boundary
$0E Top Boundary
$0D Bottom Boundary
- All other values in the map are the player's target scale at that position on the screen.
- The knight's scale is eased toward the target scale found in the screen map to make the knights appear to be further or closer to the player as they traverse the different levels of the background scenery.
- Scale range:
$A0 Smallest Scale
$C8 Largest Scale
- The knights image are three separate pieces: Head, Shoulders, Sword & Arms. (There might be another component as there is some vector data that isn't directly referenced by the code that I don't know what it's for... $64C1-$64D5)
- There is different vector data for the head of each knight.
- There are 36 Sword and Arms frames which are mirrored, for a total of 72 frames of animation for the entire sweep of each knight's sword.
- The knights head and body turn to face the opposing knight.
- The sword glow consists of 6 frames of animation. They glow brightly when the player's swords are touching.
- When the players swords are touching (and glowing) each knight's x,y movement effects the other knight's x,y position. This allows a skilled player to push the opposing knight into a pit and score.
Polar to Cartesian Conversion:
- To achieve the effect of a knight's head and body turning toward the opposing knight, the game converts the x,y cartesian coordinates of the knights' bodies to polar coordinates (radius, polar angle). This angle is then used as a target angle to gradually rotate toward. The game also calculates a Body-Head Rotation Difference, so that the knight's head rotation stops at an appropriate angle.
- Space Wars was the first vector game to utilize polar coordinates (radius & polar angle, rather than x & y). To convert between the two it used a 32 byte lookup table of Sine & cosine values converted into 8-bit values.
- Warrior expands on this system by utilizing a lookup table of 255 values ($5E9C-$5F9B) for greater accuracy.
- Polar Coordinates would continue to be used in most other Cinematronics games. The code would be further refined and Rip Off, Star Castle, Armor Attack, Solar Quest and Demon all use the same (now 90 byte) sine & cosine lookup table.
- My understanding of this is incomplete...
- The sword x,y location is within a "sword box" superimposed over each knight. As the sword x,y location moves from the player's input, the program chooses the appropriate animation frame to display that location. (How?)
- Since the knights rotate as they swing, this "sword box" also rotates, making the simple system
look more realistic. Removing the rotation revealed the "sword box".
The game does a number of collision checks:
- Check if Players Swords Are Touching
- Check to see if knights are too close together.
- Collision Check: Left Player: Sword and Right Player: Body
- Collision Check: Right Player: Sword and Left Player: Body
- Collision Check (type 2) Between: (My understanding of this is incomplete...)
Current Player Sword and Opposite Player: Body
AND Current Player Sword and Current Player: Sword Glow
*** This check removed in 4J_v2 to improve gameplay and make scoring easier. This is the "armor check". I'm not sure what Tim Skelly's intention was with this check. When it was removed to see it's effect on the game, I found that the gameplay was, to me, improved. There is no velocity variable associated with the swords.
- Collision Check (type 2) Between:
Current Player and Other Player's Sword
AND Current Player and Other Player's Sword Glow
The game code runs as if it is in banks 5 & 6 ($5000-$6FFF). However the bank switching hardware on 8k boards only looks at bit-0 of the memory bank set using "setp", so its still bank 1 & 2 ($1000-$2FFF).
Tim Skelly did this in his other games as well. It seems to be a "byte saving" technique. The SETP command is used both to bank switch between roms and to switch between the game's 16 banks of 16 bytes of ram. By storing variables in certain banks, when the SETP command is used to jump to a memory location in rom the memory location in ram that will be accessed is already set where the variables exist.
Very early Pre-programmed attract mode which runs the same routine of moves each time.
Turned on by dipswitch. Used by operators to line up monitor image with cabinet artwork.
Easter Eggs or Hidden Code:
None that I've noticed
Bank $5 ($1): $1B (27) Bytes
Bank $6 ($2): $1E (30) Bytes
4 Joystick Version:
The move to a two player version from the the code doesn't appear to be a last minute patch, but rather a decision that was earlier in the game's design. The inputs ARE spaced out as if they were changed from an original 4 joystick spec. The code and attract mode were built with two joysticks in mind and adding the additional controls and required a number of changes and additional variables.
5000-5060 Start & Init Variables 5061-507D Game Over 507E-5097 Reset Variables for Attract Mode 5098-50DF Coinage & Timer Dips 50E0-50FF Start Game Main Loop: 5100-5132 Handle Coins 5133-5159 Read Player Inputs 515A-516C Adjust Directional Input: Right Player 516D-517F Adjust Directional Input: Left Player 5180-51AE Adjust Directional Input First Done with Right Player (001) Then Done with Left Player (000) 51AF-51B8 Link Directional Movement if Swords Touching 51B9-51D6 Copy Left Player to Current Player and Goto Update Current Player 51D7-51F2 Copy Current Player to Left Player 51F3-5210 Copy Right Player to Current Player 5211 Update Current Player: 5226-524A Dead 524B-5295 Regenerate Dead Player 5296-52BB Regenerating 52BC Alive: 52BC-533F Pitfall 5340-5352 Directional Input 5353-5477 Swinging Sword 535C-538C Initial Calculations & Conversions 538D-53D5 Change Sword Orientation Based on Directional Input 53D6-53ED Adjust Added Rotation Based on Sword Orientation X 53EE-5405 Adjust Added Rotation Based on Sword Orientation Y 5406-5422 Update Current Player: Body Rotation 5423-5444 Handle Sword Mirroring 5445-546A Lookup Knight Sword Vector Data Offset 546B-5477 Goto Subroutine: Update Current Player, Return to $5586 5478-5585 Moving 5482-54B3 Change Player Location Based on Directional Input 54B4-54F5 Keep Player On Screen 54F6-5512 Skip Collision Checks and Goto Subroutine: Update Current Player, Return to $5586? 5513 Collision Checks: 5513-5528 Players too Close? If So, Set Status to: Invalid Move, Goto $5586 5529-552E Goto Subroutine: Update Current Player, Return to $552F 552F-5551 Collision Check 2: Between ??? 5552-5585 Collision Check 2: Between Current Player and Other Player's Sword 5586-558B Switch to Update Right Player ($51D7) 558C-55A8 Copy Current Player to Right Player 55A9-55C5 Check If Players Swords Unable to Touch 55C6-5614 Check if Players Swords Are Touching Set-up 5615-5649 Handle Sword Hum: Check if Players Swords Are Touching 564A-566A Collision Check: Left Player: Sword and Right Player: Body 5669-5688 Left Player Scores 5689-56A4 Collision Check: Right Player: Sword and Left Player: Body 56A5-571F Subroutine: Collision Check 5720-5741 Right Player Scores 5742-5751 Play Game Sounds 5752-5758 Check For Service Mode 5759-57BC Draw Scores & Timer 57BD-581F Draw Left Player 5820-588B Draw Right Player 588C-589E Cold Start Inhibit 589F-58C3 Game Timer 58C4-5915 Service Mode 5916-5966 Service Mode: Vector Data 5967-598A --- Copyright Text --- 598B-59AA Attract Mode: Timer 59AB-59D1 Attract Mode: Demo Input 59D2-5A08 Attract Mode: Read Data 5A09-5A21 Subroutine: Copy $10 Bytes 5A22-5CD2 Subroutine: Update Current Player 5A22-5AA0 Calculate Target Angle between Player Bodies Calculate Distance Between Current Player and Opposite Player X Calculate Distance Between Current Player and Opposite Player Y Adjust for Data Lookup Lookup Data for Cartesian to Polar Conversion 5AA1-5ADE Rotate Current Player: Head to Target Angle 5ADF-5B0C Calculate Body-Head Rotation Difference 5B0D-5B38 Swinging Sword: Rotate Head Toward Target Angle Based on Body Rotation 5B39-5B5B Moving: Rotate Body Toward Target Angle Slowly 5B5C-5B93 Update Sword & Sword Glow Goto Subroutine: Convert Polar to Cartesian: Current Player: Body Rotation & Scale Goto Subroutine: Lookup & Adjust Vector Data Add Current Player Body XY to Result and Store in Sword XY Goto Subroutine: Lookup & Adjust Vector Data Add Current Player Body XY to Result and Store in Sword Glow XY 5B94-5B9E Read Screen Data: Setup (Moving does both, swinging sword runs only its code) 5B9F-5BC5 Moving: Read Screen Data for Body XY Location 5BCC-5BDB Scale Data: Ease Current Player: Scale Toward Screen Data Scale 5BDC-5BE8 Not Scale Data: 5BE9-5C2B Screen Data = Pit 5C2C-5C55 Screen Data = Safe Zone 5C56-5C7A Swinging Sword: Read screen Data for Sword XY Location 5C7B-5CD2 Check for Invalid Sword Moves 5CD3-5D3E Subroutine: Collision Check 2 5D3F-5DB8 Subroutine: Draw Vectors 5DB9-5DDB Subroutine: Recalibrate Beam 5DDC-5E9B Data: Screen Data 5E9C-5F9B Data: Convert Cartesian to Polar 5F9C-5FE3 Data: Knight Sword Vector Data Offset Pointers 5FE4-5FFF --- Garbage? ---> 6000-609B Subroutine: Convert Polar to Cartesian 609C-60C9 Subroutine: Vector Data Lookup 60CA-6164 Subroutine: Adjust Vector Data 6165-61AD Subroutine: Draw A Number 61AE-6227 Subroutine: Draw Digit 6228-62E3 Vector Data: Digits 62E4-639C Subroutine: Draw Sword Glow 639D-6402 Vector Data: Sword Glow (6 Frames) 6403-6426 --- Copyright Text --- 6427-642E Attract Mode: Read Data 642F-64A7 Data: Attract Mode 64A8-64C0 Vector Data: Shoulders 64C1-64D5 Vector Data: 64D6-650E Vector Data: Left Player: Head 650F-653F Vector Data: Right Player: Head 6540-6FC3 Vector Data: 36 Sword & Arms Frames 6FC4-6FE0 Data: For Convert Polar to Cartesian 6FE1-6FFF --- Garbage? --->
5/17/2015: Initial Draft