easmith Posted March 1, 2019 Share Posted March 1, 2019 (edited) 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 April 9, 2019 by easmith 3 Quote Link to comment Share on other sites More sharing options...
Nukey Shay Posted March 1, 2019 Share Posted March 1, 2019 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. Quote Link to comment Share on other sites More sharing options...
AkashicRecord Posted March 2, 2019 Share Posted March 2, 2019 Have you seen Dennis Debro's disassembly of Al Miller's Basketball? Quote Link to comment Share on other sites More sharing options...
easmith Posted March 2, 2019 Author Share Posted March 2, 2019 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 Quote Link to comment Share on other sites More sharing options...
Nukey Shay Posted March 2, 2019 Share Posted March 2, 2019 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). Quote Link to comment Share on other sites More sharing options...
easmith Posted March 2, 2019 Author Share Posted March 2, 2019 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. 1 Quote Link to comment Share on other sites More sharing options...
Nukey Shay Posted March 2, 2019 Share Posted March 2, 2019 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. Quote Link to comment Share on other sites More sharing options...
Brian O Posted March 2, 2019 Share Posted March 2, 2019 This is looking great. Can't wait to give it a try. Quote Link to comment Share on other sites More sharing options...
easmith Posted March 3, 2019 Author Share Posted March 3, 2019 (edited) 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 March 11, 2019 by easmith 1 Quote Link to comment Share on other sites More sharing options...
Nukey Shay Posted March 3, 2019 Share Posted March 3, 2019 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 Quote Link to comment Share on other sites More sharing options...
easmith Posted March 4, 2019 Author Share Posted March 4, 2019 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! Quote Link to comment Share on other sites More sharing options...
easmith Posted March 4, 2019 Author Share Posted March 4, 2019 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 Quote Link to comment Share on other sites More sharing options...
+Karl G Posted March 4, 2019 Share Posted March 4, 2019 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. Quote Link to comment Share on other sites More sharing options...
easmith Posted March 4, 2019 Author Share Posted March 4, 2019 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 Quote Link to comment Share on other sites More sharing options...
easmith Posted March 4, 2019 Author Share Posted March 4, 2019 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 . Quote Link to comment Share on other sites More sharing options...
Nukey Shay Posted March 4, 2019 Share Posted March 4, 2019 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. Quote Link to comment Share on other sites More sharing options...
easmith Posted March 8, 2019 Author Share Posted March 8, 2019 (edited) 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 March 11, 2019 by easmith 5 Quote Link to comment Share on other sites More sharing options...
atarifan88 Posted March 8, 2019 Share Posted March 8, 2019 (edited) For ideas on the missed shot sound, see Intellivision's NBA Basketball. Edited March 8, 2019 by atarifan88 Quote Link to comment Share on other sites More sharing options...
+Karl G Posted March 8, 2019 Share Posted March 8, 2019 It's looking good so far! Quote Link to comment Share on other sites More sharing options...
Brian O Posted March 11, 2019 Share Posted March 11, 2019 This looks great! Quote Link to comment Share on other sites More sharing options...
easmith Posted March 11, 2019 Author Share Posted March 11, 2019 (edited) 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 March 23, 2019 by easmith 1 Quote Link to comment Share on other sites More sharing options...
Thomas Jentzsch Posted March 11, 2019 Share Posted March 11, 2019 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. Quote Link to comment Share on other sites More sharing options...
easmith Posted March 11, 2019 Author Share Posted March 11, 2019 (edited) 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 Edited March 12, 2019 by easmith 1 Quote Link to comment Share on other sites More sharing options...
easmith Posted March 12, 2019 Author Share Posted March 12, 2019 (edited) 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 March 13, 2019 by easmith 1 Quote Link to comment Share on other sites More sharing options...
easmith Posted March 13, 2019 Author Share Posted March 13, 2019 (edited) 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 March 23, 2019 by easmith Quote Link to comment Share on other sites More sharing options...
Recommended Posts
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.