Jump to content

Alkadian

Members
  • Posts

    69
  • Joined

  • Last visited

Everything posted by Alkadian

  1. @nanochess, Thank you so much for clarifying it! Very much appreciated. I am having a fantastic journey by reading your books and getting such a great support/assistance in this awesome forum from very knowledgeable and kind people!
  2. Hi, I am back again for seeking further help! It is just that I really want to understand each line of the code before moving on! With reference to the procedure below: rebound: PROCEDURE IF y < c - 3 THEN RETURN IF y > c + 15 THEN RETURN IF y < c THEN d = 0 ELSE d = (y - c) / 2 END IF ... END I understand the following: 1. We first check if y<c-3 because we want to see if the y position of the ball is above the y position of the player (in fact it is c-3 and not c-4 because we want to see if there is a collision between the top pixels of the player and the bottom pixels of the ball). 2. We then check if y>c+15 because we want to see if the y position of the ball is below the y position of the player (in fact it is c+15 and not c+16 because we want to see if there is a collision between the bottom pixels of the player and the top pixels of the ball). 3. I don't understand why when we check if y<c we then set d=0. In this case when y<c the ball should still be above the player and we should return to the point of the code where we called the procedure 4. I don't understand why we then set d = (y - c) / 2. Is this because d can only be 16 values in total and we are only considering 8 to be in one of the 8 scenarios in the procedure below? get_angle: PROCEDURE IF d = 0 THEN #dy = -2:IF #dx < 0 THEN #dx = 1 ELSE #dx = -1 IF d = 1 THEN #dy = -2:IF #dx < 0 THEN #dx = 2 ELSE #dx = -2 IF d = 2 THEN #dy = -1:IF #dx < 0 THEN #dx = 2 ELSE #dx = -2 IF d = 3 THEN #dy = 0:IF #dx < 0 THEN #dx = 2 ELSE #dx = -2 IF d = 4 THEN #dy = 0:IF #dx < 0 THEN #dx = 2 ELSE #dx = -2 IF d = 5 THEN #dy = 1:IF #dx < 0 THEN #dx = 2 ELSE #dx = -2 IF d = 6 THEN #dy = 2:IF #dx < 0 THEN #dx = 2 ELSE #dx = -2 IF d = 7 THEN #dy = 2:IF #dx < 0 THEN #dx = 1 ELSE #dx = -1 END Many thanks in advance
  3. @DZ-Jay, Thank you so much for clarifying all my doubts! Very much appreciated!! Yes it all makes sense! Thank a lot again!
  4. Hi @DZ-Jay, I was reading again your notes and I have just realised that you have mentioned that the origin of the ball is its top-right corner? I thought that the origin of any sprites was actually the top-left. Would you please confirm it? Also assuming that that's the case, am I right in saying that we can only check if x>x1 and not x>x1-4. This would apply to the second player as well so we could use: IF x > x1 AND x < x1 + 4 'for player 1 on the left IF x > x2 AND x < x2 + 4 'for player 2 on the right Actually looking at the player on the right, would you agree that we could use the condition below: X2 < X+4 < X2 +4 Apologies if I am missing the obvious! Many thanks!
  5. Haha, sorry about that 😉 Absolutely! Thank you very much indeed! Very clear explanations. Very, very helpful! Many thanks again for such a thorough review!
  6. Hi, Thanks a lot. That helped me a lot indeed. I didn't think that it was related to sub-mixel movement! I am now stuck with something else on the book. I don't understand why the ball in its old position is drawn elongated when checking collision of the ball with the top and bottom walls and when checking if the ball is exiting the screen. Then the ball is drawn fatter when checking if the ball crosses one of the paddles. Thanks so much for helping out! Much appreciated
  7. Hi, Sure, no probs at all. Really, whenever you get a chance. Thanks Oh! My bad, you are right about that! Thanks for clarifying that. Thanks! I have already implemented your suggestion. Cool stuff! Also I would really appreciate, when you get a chance, if you could explain to me the code on page 32: IF ball THEN ball_current = ball_current + ball_speed IF ball_current >= $40 THEN ball_current = ball_current - $40 I don't get why the value $40. Thanks a lot!
  8. Well, I have made some progress here! It is sort of working I have added a title screen at the beginning as you kindly suggested, added a few WAIT and then I have changed the restart procedure by adding the initial ball coordinates, so it starts from the same original position again! I have had missed that before. restart: PROCEDURE d = rand(255) % 6 x=85 y=50 END Hopefully with your feedback it will run even smoother my_pong.bas my_pong.rom
  9. Thanks a lot for looking at it for me! I have just attached the files in my previous post. I will go though every single point you made above. Looking forward to your further feedback
  10. Hi, From a pure learning point of view and alway for having fun, I have decided to start from scratch this game based on my own interpretation of Pong logic game. Basically at the moment I am looking at the very start of the game when the ball is roughly in the centre of the screen and based on a random number d (between 1 and 6) it can only go into 6 directions. Then just for testing purposes, as soon as the ball hits the position y=8 or y=96, I would like to restart the game and get a new random number d so that the game starts with the ball moving to a different direction. But I am facing the two issues below: 1. Every time I run the .rom file the ball always gets the same direction. Obviously if I manually set a value for d then I do get different direction. 2. When the ball reaches y=8 for example nothing happens. Please see the code below: CLS MODE 0,2,0,0,0 WAIT DEFINE 1,1,bitmap1 x=85 y=50 d = rand % 6 loop: IF d=1 THEN dx=2 : dy=0 IF d=2 THEN dx=-2 : dy=0 IF d=3 THEN dx=1 : dy=1 IF d=4 THEN dx=-1 : dy=1 IF d=5 THEN dx=1 : dy=-1 IF d=6 THEN dx=-1 : dy=-1 IF y=8 THEN GOSUB restart IF y=96 THEN GOSUB restart x=x+dx y=y+dy SPRITE 0, $0300+x, $0100+y, $0807 + 1 * 8 GOTO loop bitmap1: BITMAP "##......" BITMAP "##......" BITMAP "........" BITMAP "........" BITMAP "........" BITMAP "........" BITMAP "........" BITMAP "........" restart: PROCEDURE d = rand % 6 END Could you please help me out? Thanks a lot! my_pong.bas my_pong.rom
  11. @DZ-Jay, thanks a lot. Things are getting way clearer to me. i just need to digest it all now
  12. Awesome, thanks a lot for clarifying and for your further comments which are always very helpful. It makes sense now. One final question please, could you please let me know why we always check if #dx<0 in the if statements, for example: IF d = 0 THEN #dy = -2:IF #dx < 0 THEN #dx = 1 ELSE #dx = -1 Infact #dx it is not even declared up to that point so I wonder how do we know if it is positive or negative? 🤔 Thanks!
  13. @DZ-Jay, that's great! Many thanks for your comprehensive clarifications! Very helpful indeed. I am now experimenting with different values for the pixels along X and Y to see how it works. Looking forward to your next post regarding my other query. I would also appreciate a ton if you could also explain to me why we always check if #dx<0 in the formulas for computing d, expecially because #dx it is not even declared up to that point so I woinder how do we know if it is positive or negative? 🤔 Thanks for your patience!
  14. @DZ-Jay, Many thanks as usual for your very clear explanations. Very much appreciated. Would you please help me further with the above? Does that mean that I could also move 1 pixel along the Y axis instead of 2 pixels to move North like when we move to North-East? Please see below the whole code: CLS PRINT AT 0 COLOR 1 FOR c = 1 TO 20 PRINT "\256" NEXT c PRINT AT 220 FOR c = 1 to 20 PRINT "\257" NEXT c PRINT AT 9, "\258" FOR c = 1 TO 10 PRINT AT c * 20 + 9, "\259" NEXT c PRINT AT 229, "\260" GOSUB update_score x1 = 21 y1 = 42 x2 = 139 y2 = 42 GOSUB restart_ball x = ox y = oy #dx = -2 #dy = -2 ball_speed = $20 ball_current = 0 ' ' Main game loop ' ball_loop: WAIT IF sound_counter > 0 THEN sound_counter = sound_counter - 1 IF sound_counter = 0 THEN SOUND 2, 1, 0 END IF SPRITE 0, $0708 + x1, $0208 + y1, $0800 + 5 * 8 + 1 SPRITE 1, $0708 + x2, $0208 + y2, $0800 + 5 * 8 + 2 IF ball = 0 THEN SPRITE 2, 0 ELSE SPRITE 2, $0708 + x, $0208 + y, $0800 + 6 * 8 + 6 END IF IF cont1.up THEN IF y1 > 6 THEN y1 = y1 - 2 IF cont1.down THEN IF y1 < 74 THEN y1 = y1 + 2 IF cont2.up THEN IF y2 > 6 THEN y2 = y2 - 2 IF cont2.down THEN IF y2 < 74 THEN y2 = y2 + 2 IF ball THEN ball_current = ball_current + ball_speed IF ball_current >= $40 THEN ball_current = ball_current - $40 ox = x oy = y x = x + #dx y = y + #dy IF oy + #dy < 2 THEN #dy = -#dy oy = 2 - #dy GOSUB ball END IF IF oy + #dy > 90 THEN #dy = -#dy oy = 90 - #dy GOSUB ball END IF IF ox + #dx < 2 THEN GOSUB ball_out GOSUB restart_ball END IF IF ox + #dx > 158 THEN GOSUB ball_out GOSUB restart_ball END IF IF x > x1 - 4 AND x < x1 + 4 THEN c = y1 GOSUB rebound END IF IF x > x2 - 4 AND x < x2 + 4 THEN c = y2 GOSUB rebound END IF x = ox + #dx y = oy + #dy END IF ELSE c = cont AND $E0 IF (c = $a0) + (c = $c0) + (c = $60) THEN ball = 1 END IF GOTO ball_loop ' ' Ball touched wall ' ball: PROCEDURE SOUND 2,500,48 SOUND 3,400,9 sound_counter = 10 END ' ' Ball came out of field ' ball_out: PROCEDURE IF x < 80 THEN score2 = score2 + 1 ELSE score1 = score1 + 1 END IF GOSUB update_score SOUND 2,330,48 SOUND 3,70,10 sound_counter = 15 END ' ' Update score for both players ' update_score: PROCEDURE ' Show score at 2 digits aligned to right PRINT AT 27 COLOR 1,<.2>score1 ' Show score as digits aligned to left PRINT AT 31 COLOR 2,<>score2 END ' ' Restart the ball ' restart_ball: PROCEDURE d = RAND % 8 ox = 80 oy = 48 ball = 0 GOSUB get_angle END ' ' Rebound procedure ' Check if ball hits paddle (y coordinate, x already checked) ' rebound: PROCEDURE IF y < c - 3 THEN RETURN IF y > c + 15 THEN RETURN IF y < c THEN d = 0 ELSE d = (y - c) / 2 END IF GOSUB get_angle IF ball_speed < $40 THEN ball_speed = ball_speed + 1 SOUND 2,150,48 SOUND 3,300,9 sound_counter = 5 END ' ' Get angle per paddle position ' Variable d contains the hit position. ' Returns dx and dy with new direction. ' get_angle: PROCEDURE IF d = 0 THEN #dy = -2:IF #dx < 0 THEN #dx = 1 ELSE #dx = -1 IF d = 1 THEN #dy = -2:IF #dx < 0 THEN #dx = 2 ELSE #dx = -2 IF d = 2 THEN #dy = -1:IF #dx < 0 THEN #dx = 2 ELSE #dx = -2 IF d = 3 THEN #dy = 0:IF #dx < 0 THEN #dx = 2 ELSE #dx = -2 IF d = 4 THEN #dy = 0:IF #dx < 0 THEN #dx = 2 ELSE #dx = -2 IF d = 5 THEN #dy = 1:IF #dx < 0 THEN #dx = 2 ELSE #dx = -2 IF d = 6 THEN #dy = 2:IF #dx < 0 THEN #dx = 2 ELSE #dx = -2 IF d = 7 THEN #dy = 2:IF #dx < 0 THEN #dx = 1 ELSE #dx = -1 END If I understand correctly starting from the section below: GOSUB restart_ball x = ox y = oy #dx = -2 #dy = -2 ball_speed = $20 ball_current = 0 we jump to the restart_ball() procedure which in sequence calls the get_angle() procedure, then we return to the restart_ball() procedure and then goes back to : GOSUB restart_ball x = ox y = oy #dx = -2 #dy = -2 ball_speed = $20 ball_current = 0 But at this point #dx and #dy get overridden. Thanks a lot!
  15. Hi, I am just going through the game logic of "A Game of Ball" by following the code on Oscar's book (page 32-34). With reference to the code below: restart_ball: PROCEDURE d = RAND % 8 ox = 80 oy = 48 ball = 0 GOSUB get_angle END I understand that d (direction?) contains a random number between 0 and 8 (RAND gives you a random number between 0 and 255 and then modulo 8). ox and oy contain the initial position of the ball, the sprite ball is disabled (until you press one of the side-buttons). Then it jumps to the subroutine get_angle: ' ' Get angle per paddle position ' Variable d contains the hit position. ' Returns dx and dy with new direction. ' get_angle: PROCEDURE IF d = 0 THEN #dy = -2:IF #dx < 0 THEN #dx = 1 ELSE #dx = -1 IF d = 1 THEN #dy = -2:IF #dx < 0 THEN #dx = 2 ELSE #dx = -2 IF d = 2 THEN #dy = -1:IF #dx < 0 THEN #dx = 2 ELSE #dx = -2 IF d = 3 THEN #dy = 0:IF #dx < 0 THEN #dx = 2 ELSE #dx = -2 IF d = 4 THEN #dy = 0:IF #dx < 0 THEN #dx = 2 ELSE #dx = -2 IF d = 5 THEN #dy = 1:IF #dx < 0 THEN #dx = 2 ELSE #dx = -2 IF d = 6 THEN #dy = 2:IF #dx < 0 THEN #dx = 2 ELSE #dx = -2 IF d = 7 THEN #dy = 2:IF #dx < 0 THEN #dx = 1 ELSE #dx = -1 END This is where I am getting confused, as I don't understand why the variable d can only be from 0 to 7. Does that mean that we can only have 8 directions in total? Could you please explain the meaning of: #dx = -2,-1,0,1,2 (2 pixels to the left, 1 pixel to left, neutral, 1 pixel to the right, 2 pixels to the right and based on these values we know the angle/direction? d=#dy/#dx) #dy = -2,-1,0,1,2 (2 pixels up, 1 pixel up, neutral, 1 pixel down, 2 pixels down and based on these values we know the angle/direction? d=#dx/#dx) Also, let's say that we are in the scenario d=7 with #dy = 2 and #dx = -1. Then when we jump back to the code: GOSUB restart_ball x = ox y = oy #dx = -2 #dy = -2 ball_speed = $20 ball_current = 0 #dx and #dy get both set to -2 overriding the previous values set in the get_angle PROCEDURE. Sorry for my confusion but I really want to get these things right. Thanks a lot!
  16. @DZ-Jay, many thanks for your further clarifications. Very clear indeed. I guess from a clock cycles point of view, the code provided in the book is better as it takes less instructions.
  17. Hi, I am reading back Oscar's book, and with reference to Chapter 4, Paragraph 4.2 and the code below: CLS MODE 0,2,0,0,0 WAIT DEFINE 0,1,my_bitmap PRINT AT 0 COLOR 1 FOR C = 1 TO 20 PRINT "\256" NEXT C loop: GOTO loop my_bitmap: BITMAP "11111111" BITMAP "00000000" BITMAP "11111111" BITMAP "00000000" BITMAP "11111111" BITMAP "00000000" BITMAP "00000000" BITMAP "00000000" gives the same result if I replace the section in red above with : FOR C = 0 TO 19 PRINT AT C COLOR 1, "\256" NEXT C which is equivalent to FOR C= 0 TO 19 #BACKTAB(C)=$0801 WAIT NEXT C What I don't follow with the original way is that how the compiler knows that every iteration we move from card 0 to card 1 to card 2 etc. if the position 0 is fixed? Thanks! EDIt: Of course! I have figured it out! That is equivalent to write PRINT "\256" 20 times! Oh dear, time to do a break then
  18. Hi, I am starting a new thread following my previous post, hoping that it could be help somebody else in future: Below the advice given by @DZ-Jay: ----------------------------------------------------------------------------------------------------------- Of course! Just follow it with a comma and the variable: PRINT AT ScreenPos(7, 0) COLOR CS_YELLOW, "Contents of variable y:", y Just bear in mind that it will treat all variables as if they were characters and try to convert them to a GROM or GRAM card. If you want IntyBASIC to interpret the variable as a number -- essentially converting it to a decimal numeric string -- you need to use the "<>" directive, as described in the IntyBASIC manual: PRINT <>expr ' Simple number PRINT <const>expr ' Right-aligned with zeroes to 'const' size. PRINT <.const>expr ' Right-aligned with spaces to 'const' size. So, for your example above, if "y" is numeric, you can use: PRINT AT ScreenPos(7, 0) COLOR CS_YELLOW, "Contents of variable y:", <>y For scores and such which typically have a specific field size, prefixed with zeroes or spaces, you use one of the other two variations: ' Print score in a four-digit string, with leading zeros PRINT AT ScreenPos(12, 0) COLOR CS_RED, "P1:", <4>score What happens if you forget the "<>" modifier? The contents of the variable will be interpreted as a card number, multiplied by 8, and indexed into either GRAM or GROM, wherever it may appear to point. In other words, the arguments to PRINT AT after the position are used to compose a BACKTAB card data word, for instance: ' The following: ' PRINT AT ScreenPos(7) COLOR CS_YELLOW, "Contents of variable y:", y ' is the same as: #Backtab(7) = CS_YELLOW + (y * 8) So ... be careful with that. -dZ. ------------------------------------------------------------------------------------ I am pleased to report that it worked like a charm. Of course I have had to use <>#y and <>#x in my specific case, as pointed out by @artrag x and y are16-bit variables! Below the code which I have used for testing: INCLUDE "constants.bas" CLS MODE 0,2,0,0,0 WAIT c=0 loop: WAIT #BACKTAB(c)=$0007 + 3 * 8 #x=#BACKTAB(c) #y=(#x and $07F8) / 8 #BACKTAB(#y+1)=$0007 + 4 * 8 PRINT AT ScreenPos(20, 0) COLOR CS_YELLOW, "Contents of variable y:", <>#y PRINT AT ScreenPos(60, 0) COLOR CS_YELLOW, "Contents of variable x:", <>#x GOTO loop Thanks!
  19. Thanks I will! Agreed about the separate thread, it makes sense.
  20. Awesome! Many thanks for providing me with all the required information. I will experiment and i will post back if I struggle with something, if you don't mind
  21. @DZ-Jay, thanks a lot for your further very clear explanations! They are always very helpful! Your notes regarding the WAIT made a lot of sense to me thanks for clarifying that! You are absolutely right about the use of Constants.bas. At the moment I am using the magic numbers as I am still learning the actual meaning of them. Once I will digest it I will definitely switch to the Constants.bas. As you rightly say it makes the code a lot easier to read and maintenable. Thanks a lot for for rewriting it for me. Much appreciated! I have a question, if I may. Would it be possible to use the PRINT function to print the contents of a variable? Something like: PRINT AT 7 COLOR 6, "Contents of variable y" Thanks so much! You guys are a treasure here!
  22. @artrag, thanks so much for pointing that out. Shame on me as I should have noted that 16-bit variables always need a # in front of them! I did read it on @nanochess's book (page 9)and completely forgot about that! Thanks again! That did the trick and I am very happy to report that the code below is now working as intended! CLS MODE 0,2,0,0,0 WAIT c=0 loop: #BACKTAB(c)=$0007 + 3 * 8 #y=(#BACKTAB(c) and $07F8) / 8 #BACKTAB(#y+1)=$0007 + 3 * 8 GOTO loop
  23. Hi, I have been experimenting with masking either the ROM card number or the RAM card number from the backtab. The bitmask for the GRAM in mode 1 is: 0000000111111000=$01F8 The bitmask for the GROM in mode 0 is: 0000011111111000=$07F8 The code seems to work fine when masking the GRAM. In fact the second bitmap gets displayed in the correct place y+4=1+4=5 CLS MODE 1 WAIT DEFINE 1,1,bitmap1 c=10 loop: #backtab(c)=$0800 + 1 * 8 + 7 wait x=#backtab(c) y=(x AND $01F8) /8 #backtab(y+4)=$0800 + 1 * 8 + 7 GOTO loop bitmap1: BITMAP "...##..." BITMAP "#.#..#.#" BITMAP ".######." BITMAP "..#..#.." BITMAP ".#....#." BITMAP "#......#" BITMAP ".######." BITMAP "........" However the code below it doesn't seem to work when masking the GROM. In fact the GROM character # gets displayed in a different position and not at position y+1=3+1=4 CLS MODE 0,2,0,0,0 WAIT c=0 loop: #BACKTAB(c)=$0007 + 3 * 8 WAIT #BACKTAB(c)=x y=(x and $07F8) / 8 #BACKTAB(y+1)=$0007 + 3 * 8 GOTO loop Could you please explain to me what I am doing wrong? Also I have noticed that if I don't put WAIT after #BACKTAB(c)=$0007 + 3 * 8, then the first GROM character doesn't get displayed at all. Thanks!
  24. Hi, Again nothing special here. But I am now getting more familiar with the loops instructions and the MUSIC statement! I am really having a lot of fun. I have also experimented GIMP with INTYTColor and it works great! I hope the tune will sound familiar! Just to share my little achievements alternate.rom
×
×
  • Create New...