Jump to content
IGNORED

One-on-One / HORSE / 3 pt Shootout (ASM)


easmith

Recommended Posts

latest rev: http://atariage.com/forums/topic/288985-one-on-one-atari-2600-asm-1-or-2-players/?p=4254408

 

Started working on a game inspired by the old Bird vs. Dr J. One -on -one . No gameplay yet, but have Kernel "proof of concept."

Plan is to have similar controls as One on One ( tap button to turn around, hold button a little to pick up dribble and pump fake. Hold button longer to jump shoot .

Release button at proper time for shot). Ability to steal and block on defense.

 

Game to 21 , win by 2, with winners outs or losers outs.

 

Also want mini-games for HORSE and 3 point contest .

 

Lots of work to do !

 

I currently have flicker , and only single- colored players because of needing the following objects on screen that must be updated

 

-- PF 1 and PF 2 graphics

--- Background color

---- P1 graphic

--- P0 graphic

--- ball

---- ball shadow.

 

So currently I am drawing P0 and shadow on a frame , and P1 and ball on frame ( if P0 has ball so P1 can steal or block by collision register with ball-- vice versa if P1 has ball) . For rebounds and keeping players from running through each other will have to use different collision detection .

 

I would really like to have multicolored players , but am currently out of cycles in my single line kernel. Also am currently a few cycles short for adding animation.

 

If anyone who is a 2LK guru would like to collaborate / help me out, I would welcome this !

 

I know about the collect tutorial but am afraid I am too dumb to understand it properly .

 

ES

Edited by easmith
  • Like 3
Link to comment
Share on other sites

You should swap the PF2/PF1 writes...PF1 currently is updated too late in the scanline (that is why the right portion is misaligned by a scanline). PF2 does not need updating until cycle 48.

 

You really ought to be using a skipdraw variant for the player objects, that will provide greater flexibility for animation. Also, enable vertical delay so that sprite updates do not need to be done within the first 22 cycles.

Link to comment
Share on other sites

You should swap the PF2/PF1 writes...PF1 currently is updated too late in the scanline (that is why the right portion is misaligned by a scanline). PF2 does not need updating until cycle 48.

 

You really ought to be using a skipdraw variant for the player objects, that will provide greater flexibility for animation. Also, enable vertical delay so that sprite updates do not need to be done within the first 22 cycles.

 

Thanks,

 

I tried to directly swap the writes to PF1 / PF2 and it made it worse . I probably need to move the PF2 earlier . I will keep experimenting .

I am not familiar with the skipdraw variant . I have always used the same method that I use here ( see attached). But I will look it up .

In the meantime , here is a sample of my current kernel if that helps .

kernelsample.asm

Link to comment
Share on other sites

Well, let's start with what you know how to do. I find it easier to keep track of cycle use when all counts are listed (including total number of cycles for the worst-case scenario). In a 2-line kernel, there is enough time to update the playfield registers and sprites (including the colors). Here. I've added 2 variables for player indexes (so you can have different animation frames). These are temp variables, so you need to reset them each time going into the kernel.

 

Note: the routine assumes that the player sprite tables have matching color tables of equal length. Color zero is used as a delimiter to clear the sprite, so use color value 1 if you want to include black as a sprite color.

 

 

Continue
     ldy bgcolor,x      ;4 38
     txa                ;2 40
     sbc bally          ;3 43
     cmp #6             ;2 45
     lda #2             ;2 47
     bcc InBallRange2   ;2 49
     lda #0             ;2 51
InBallRange2
     sta WSYNC          ;3
     sta ENAM1          ;3 3
     sty COLUBK         ;3 6
     lda PF1graphics,x  ;4 10
     sta PF1            ;3 13
     lda #1             ;2 15
     cpx shadowy        ;3 18
     beq Inshadowrange2 ;2 20
     .byte $C5          ;3 23
Inshadowrange2
     asl                ;2 23
     sta ENAM0          ;3 26
     lda PF2graphics,x  ;4 30
     sta PF2            ;3 33
     lda #0             ;2 35
     cpx P0y            ;3 38
     beq Start_P0_gfx   ;2 40
     ldy P0yIndex       ;3 43
     lda P0Gfx,y        ;4 47
     sta GRP0           ;3 50
     lda P0color,y      ;4 54
     beq P0_drawn       ;2 56
Start_P0_gfx
     inc P0yIndex       ;5 61
P0_drawn
     cpx P1y            ;3 64
     sta WSYNC          ;3
     sta COLUP0         ;3 3
     beq Start_P1_gfx   ;2 5
     ldy P1yIndex       ;3 8
     lda P1Gfx,y        ;4 12
     sta GRP1           ;3 15
     lda P1color,y      ;4 19
     sta COLUP1         ;3 22
     beq P1_drawn       ;2 24
Start_P1_gfx
     inc P1yIndex       ;5 29
P1_drawn
     dex                ;2 31
     bne Continue       ;2 33
     sta WSYNC
     stx COLUBK
     stx PF2
     stx PF1
     stx ENAM1
     stx ENAM0
     stx GRP0
     stx GRP1

 

Notice that GRP0 is updated on cycle 50. This is fine if VDELP0 is enabled (the next write to GRP1 then updates both).

Link to comment
Share on other sites

Well, let's start with what you know how to do. I find it easier to keep track of cycle use when all counts are listed (including total number of cycles for the worst-case scenario). In a 2-line kernel, there is enough time to update the playfield registers and sprites (including the colors). Here. I've added 2 variables for player indexes (so you can have different animation frames). These are temp variables, so you need to reset them each time going into the kernel.

 

Note: the routine assumes that the player sprite tables have matching color tables of equal length. Color zero is used as a delimiter to clear the sprite, so use color value 1 if you want to include black as a sprite color.

Continue
     ldy bgcolor,x      ;4 38
     txa                ;2 40
     sbc bally          ;3 43
     cmp #6             ;2 45
     lda #2             ;2 47
     bcc InBallRange2   ;2 49
     lda #0             ;2 51
InBallRange2
     sta WSYNC          ;3
     sta ENAM1          ;3 3
     sty COLUBK         ;3 6
     lda PF1graphics,x  ;4 10
     sta PF1            ;3 13
     lda #1             ;2 15
     cpx shadowy        ;3 18
     beq Inshadowrange2 ;2 20
     .byte $C5          ;3 23
Inshadowrange2
     asl                ;2 23
     sta ENAM0          ;3 26
     lda PF2graphics,x  ;4 30
     sta PF2            ;3 33
     lda #0             ;2 35
     cpx P0y            ;3 38
     beq Start_P0_gfx   ;2 40
     ldy P0yIndex       ;3 43
     lda P0Gfx,y        ;4 47
     sta GRP0           ;3 50
     lda P0color,y      ;4 54
     beq P0_drawn       ;2 56
Start_P0_gfx
     inc P0yIndex       ;5 61
P0_drawn
     cpx P1y            ;3 64
     sta WSYNC          ;3
     sta COLUP0         ;3 3
     beq Start_P1_gfx   ;2 5
     ldy P1yIndex       ;3 8
     lda P1Gfx,y        ;4 12
     sta GRP1           ;3 15
     lda P1color,y      ;4 19
     sta COLUP1         ;3 22
     beq P1_drawn       ;2 24
Start_P1_gfx
     inc P1yIndex       ;5 29
P1_drawn
     dex                ;2 31
     bne Continue       ;2 33
     sta WSYNC
     stx COLUBK
     stx PF2
     stx PF1
     stx ENAM1
     stx ENAM0
     stx GRP0
     stx GRP1

Notice that GRP0 is updated on cycle 50. This is fine if VDELP0 is enabled (the next write to GRP1 then updates both).

 

 

 

Ok , Wow . I think I have it ! ( You have it :) ) . That just changed my world ,thanks. Now the next challenge is to figure out how to get shot arcs to look good from various spots on the court.

post-63151-0-47309500-1551547645_thumb.png

  • Like 1
Link to comment
Share on other sites

You did it already, I just shuffled the order a little. It's still possible to get the kernel down to single-line resolution...via skipdraw for the players, stack manipulation for the missiles, cycle-exact branching to eliminate WSYNC, & dedicated subkernels for the tricky spots. If flicker is still an option, you could use that so both player sprites are used on each character for 16-bit detail (no need for seperate kernels to employ that, just use temp variables in the routine). The sprite/color loading can immediately be altered to use indirect addressing if the 256-byte gfx limit becomes an issue.

Link to comment
Share on other sites

You did it already, I just shuffled the order a little. It's still possible to get the kernel down to single-line resolution...via skipdraw for the players, stack manipulation for the missiles, cycle-exact branching to eliminate WSYNC, & dedicated subkernels for the tricky spots. If flicker is still an option, you could use that so both player sprites are used on each character for 16-bit detail (no need for seperate kernels to employ that, just use temp variables in the routine). The sprite/color loading can immediately be altered to use indirect addressing if the 256-byte gfx limit becomes an issue.

 

I think I will be satisfied with the kernel for now as is .

 

Making some steady progress.

 

I wonder why when the dr j character moves vertically through the vertical plane of the bird player, the bird player graphic is slightly altered . But not other way around.

see attached

Edited by easmith
  • Like 1
Link to comment
Share on other sites

Because there is a flaw when writing the sprites I didn't notice when writing that. GRP0 (with VDEL) is only updated when GRP1 is actually written. This is skipped when initially bumping the offset to display GRP1. ENAM0 was a little late, as well.

 

 

Continue
     ldy bgcolor,x      ;4 41
     txa                ;2 43
     sbc bally          ;3 46
     cmp #6             ;2 48
     lda #2             ;2 50
     bcc InBallRange2   ;2 52
     lda #0             ;2 54
InBallRange2
     sta WSYNC          ;3
     sta ENAM1          ;3 3
     sty COLUBK         ;3 6
     lda #1             ;2 8
     cpx shadowy        ;3 11
     beq Inshadowrange2 ;2 13
     .byte $C5          ;3 16
Inshadowrange2
     asl                ;2 16
     sta ENAM0          ;3 19
     lda PF1graphics,x  ;4 23
     sta PF1            ;3 26
     lda PF2graphics,x  ;4 30
     sta PF2            ;3 33
     lda #0             ;2 35
     cpx P0y            ;3 38
     beq Start_P0_gfx   ;2 40
     ldy P0yIndex       ;3 43
     lda P0Gfx,y        ;4 47
     sta GRP0           ;3 50
     lda P0color,y      ;4 54
     beq P0_drawn       ;2 56
Start_P0_gfx
     inc P0yIndex       ;5 61
P0_drawn
     cpx P1y            ;3 64
     sta WSYNC          ;3
     sta COLUP0         ;3 3
     beq Start_P1_gfx   ;2 5
     ldy P1yIndex       ;3 8
     lda P1Gfx,y        ;4 12
     sta GRP1           ;3 15
     lda P1color,y      ;4 19
     sta COLUP1         ;3 22
     beq P1_drawn       ;2 24
     bne P1_in_progress ;3 27
Start_P1_gfx
     lda #0             ;2 8
     sta GRP1           ;3 11
P1_in_progress
     inc P1yIndex       ;5 32
P1_drawn
     dex                ;2 34
     bne Continue       ;2 36
     sta WSYNC
     stx COLUBK
     stx PF2
     stx PF1
     stx ENAM1
     stx ENAM0
     stx GRP0
     stx GRP1
Link to comment
Share on other sites

 

Because there is a flaw when writing the sprites I didn't notice when writing that. GRP0 (with VDEL) is only updated when GRP1 is actually written. This is skipped when initially bumping the offset to display GRP1. ENAM0 was a little late, as well.

Continue
     ldy bgcolor,x      ;4 41
     txa                ;2 43
     sbc bally          ;3 46
     cmp #6             ;2 48
     lda #2             ;2 50
     bcc InBallRange2   ;2 52
     lda #0             ;2 54
InBallRange2
     sta WSYNC          ;3
     sta ENAM1          ;3 3
     sty COLUBK         ;3 6
     lda #1             ;2 8
     cpx shadowy        ;3 11
     beq Inshadowrange2 ;2 13
     .byte $C5          ;3 16
Inshadowrange2
     asl                ;2 16
     sta ENAM0          ;3 19
     lda PF1graphics,x  ;4 23
     sta PF1            ;3 26
     lda PF2graphics,x  ;4 30
     sta PF2            ;3 33
     lda #0             ;2 35
     cpx P0y            ;3 38
     beq Start_P0_gfx   ;2 40
     ldy P0yIndex       ;3 43
     lda P0Gfx,y        ;4 47
     sta GRP0           ;3 50
     lda P0color,y      ;4 54
     beq P0_drawn       ;2 56
Start_P0_gfx
     inc P0yIndex       ;5 61
P0_drawn
     cpx P1y            ;3 64
     sta WSYNC          ;3
     sta COLUP0         ;3 3
     beq Start_P1_gfx   ;2 5
     ldy P1yIndex       ;3 8
     lda P1Gfx,y        ;4 12
     sta GRP1           ;3 15
     lda P1color,y      ;4 19
     sta COLUP1         ;3 22
     beq P1_drawn       ;2 24
     bne P1_in_progress ;3 27
Start_P1_gfx
     lda #0             ;2 8
     sta GRP1           ;3 11
P1_in_progress
     inc P1yIndex       ;5 32
P1_drawn
     dex                ;2 34
     bne Continue       ;2 36
     sta WSYNC
     stx COLUBK
     stx PF2
     stx PF1
     stx ENAM1
     stx ENAM0
     stx GRP0
     stx GRP1

this fixed the issue!

 

 

 

 

Link to comment
Share on other sites

Looking at Stella Programmer's guide it appears there is no way to prioritize P1 over P0 , but thought I would ask in case I missed something.

 

For this type of game it would be best to have player lower on screen to have priority

Link to comment
Share on other sites

Yeah; you just have to swap which is which as needed instead - in your case make the player lower on the screen use the P0 object even if it's logically player 1.

 

that makes sense.... Don't know if there are enough cycles in kernel remaining , but I can check

Link to comment
Share on other sites

Yeah; you just have to swap which is which as needed instead - in your case make the player lower on the screen use the P0 object even if it's logically player 1.

 

After thinking about this for a bit it seems much easier said than done . It will require also swapping out player horizontal positions and vertical positions and also would require checking any changes to P0 ram variable to be swapped to P1 depending on who is lower . Would also require a duplicate kernel . again unless I am overthinking. But might not be worth the effort .

Link to comment
Share on other sites

Use indirect vectors in the kernel instead. Then you can swap them before you position the sprites if needed. Whoever is lower onscreen gets GRP0. Very easy to set up (indirect),y addressing here, there's enough cycle time in the scanlines (currently). This actually simplifies the kernel, since the Y index would always be zero.

 

In any case, the kernel is still pretty small...so you could just go with a duplicate instead.

Link to comment
Share on other sites

Use indirect vectors in the kernel instead. Then you can swap them before you position the sprites if needed. Whoever is lower onscreen gets GRP0. Very easy to set up (indirect),y addressing here, there's enough cycle time in the scanlines (currently). This actually simplifies the kernel, since the Y index would always be zero.

 

In any case, the kernel is still pretty small...so you could just go with a duplicate instead.

 

Thank you so much NukeyShay. I have not yet worked out the priority issue, but have managed to put together a playable game. Not bad for 1 week :)

Here are the current features :

-- game can be played to any score less than 100

-- 3 pointers ( have to work on getting the curved parts of 3 point line to register correctly.

--- fouls and steals . If you get three fouls , additional fouls result in points to the opponent.

-- shots vary in make probability based on region of court and point of release ( best to release at top of jump)

-- currently the players have the same abilities. I could alter the abilities ( I believe the Dr J vs Bird game had bird slower but better outside shooter??)

here is what is still in progress:

-- HORSE mini game

-- sound for missed shot

-- more rebound variation

-- shot blocks

-- refining 3 point line recognition

--- making it so that you have to take the ball back court or beyond 3 line before shooting ( although with 2 player game you can set these rules)

--- "winners outs " option

Edited by easmith
  • Like 5
Link to comment
Share on other sites

Managed to free up enough space to add most of what I wanted, including additional game options such as Winner's Outs, option for not having to take ball backcourt after rebounding opponent's miss, and added the other game options of HORSE and Around the world . Still have to figure out swapping priority for players when P1 is below P0. Again, I give NukeyShay credit for writing the kernel.

I suggest you read the instructions below.

Gameplay Information / Game options

To change game option, hit select switch ( score must be 0-0 , otherwise press reset to restart game).

For HORSE, the tens digit in scores will change to “H”. For Around The World, will change to “A”.

Game 1 ( default)

One-On-One

To shoot: press and hold button to jump. Release button to shoot. If you do not release button before landing this will result in travelling and change of possession.

--Releasing the button at the top of jump improves probability of making shot.

-- Closer to basket = higher probability of making shot

-- Players can dunk by contacting ball to basket without releasing button. If you are to immediate right or left of goal you can move in the air toward the basket.

Backcourt Rules: Upon rebounding opponent’s miss, ball must be taken beyond the 3 point line before you can shoot. This can be disabled by Setting P0 difficulty to A.

Winner’s- Outs vs. Loser’s Outs ( aka Make it- Take it) .

-- default is loser’s outs . Setting P1 difficulty to A changes to Winner’s Outs.

Steals: Players can steal ball from opponent by moving hands in contact with ball.

-- steal will not always occur . Sometimes nothing will happen and sometimes a foul will occur

Blocks: Players can block opponent’s shots by contacting shot while jumping.

--- must be immediately after shot is released , and blocks will not always occur with apparent contact.

Fouls : While attempting to steal , player can commit a foul. After foul, players are reset to starting position. After 3 fouls have been committed, additional fouls will result in one point being added to opponent’s score and opponent keeping possession.

Scoring: 2 points or 3 points for baskets. 1 point for being fouled after 3rd time

Game will not end. Players must decide on a score to play to .

Game option 2: HORSE

Doesn’t everyone know how horse works?

Players must self-police shots and move to correct positions .

Fouls are disabled in HORSE . so if the wrong player has the ball, the other player just needs to steal ball.

Scoring: First player to earn “E” loses.

Game option 3: Around the World

Not sure if many people played this as kids, but I played it a lot.

---- -This game is self -policing . Players must keep track of their shots and must move to correct positions.

Rules: Player 0 starts at left three point line position and shoots.

If shot is made, then player moves to position 2. If miss, then player can take a second shot or stay in place and allow next player to begin turn.

If second shot is made, then player moves to next position. If second shot is missed, then player must return to position 1 and start all over .

--- First player to make shots at all 10 positions wins .

Fouls are disabled in Around the World . So if the wrong player has the ball, the other player just needs to steal ball.

Positions ( these are suggested positions – players can add or alter positions as desired , as there is no set ending to game):

See attached for diagram.

1on1-HORSE-AroundtheWorld.pdf

Edited by easmith
  • Like 1
Link to comment
Share on other sites

Why do you have the shadow of the ball below the players feet? It looks like the ball is closer than the player where it should be vice versa or the same.

 

Also, if you put the ball shadow on the feet level, the shadow color won't have to change when players overlap vertically.

Link to comment
Share on other sites

Why do you have the shadow of the ball below the players feet? It looks like the ball is closer than the player where it should be vice versa or the same.

 

Also, if you put the ball shadow on the feet level, the shadow color won't have to change when players overlap vertically.

 

The shadow is the P0 missile. So it is taking on whatever color P0 has. The shadow is 2 scanlines high due to 2LK, so if I move it up any it is two-tone unless I make the player shoes go up the leg higher, which looks worse to me. Also , whenever the shadow passes through vertical zone of P0 the colors change to P0colors. Right now P0 and P0missile are not being updated on same scan line, so if I change the P0color to black immediately before ENAM0 then every other line of P0 is black. Perhaps I can reorder so that P0 and M0 are updated on same line.....(?) and that would fix it.

 

But this is one of those imperfections that I had pretty much decided to live with. I thought the shadow would be a nice detail and make the ball easier to track, but now I wonder whether it actually adds anything. But the court markings are PF, so the ball and court markings are same color . This was another reason for the shadow-- to see where the ball is if it is over a court line.

 

Another thing I originally had was the backboard and net being white ( I think this looked better) and the Ball and court markings orange. But since they are PF also, the ball changed to white

when it was on the level of the net or Backboard.

 

something like this with an orange ball looks pretty sharp. but don't like the white ball

post-63151-0-98793400-1552364298_thumb.png

 

Edited by easmith
  • Like 1
Link to comment
Share on other sites

I think I have successfully pulled off the priority swap , so that if Dr J player is below Bird player then he changes to P0 graphic so that he shows in front.

This affected a lot of other logic that had to be adjusted when this occurs. I think I caught all of the things that were affected but not sure.

This version now has the brown/white color scheme which I prefer except for the white ball :(

 

EDIT: nope ! found some bugs. Have to try to fix them..

 

 

reverting to last known good version for now

Edited by easmith
  • Like 1
Link to comment
Share on other sites

I have it working now to where the priority swap only happens when J has ball and is below B. At least this shows J on top when has ball.

 

 

catching a few bugs with extensive testing.... fixing one seems to cause another . Fingers crossed on this one..

 

 

3/17

 

switched shadow to M1 but forgot to change 3 point routine which needs shadow behind line in curved section . fixed now

1on1-HORSE-AroundtheWorld.pdf

Edited by easmith
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...