Jump to content

DZ-Jay

+AtariAge Subscriber
  • Posts

    14,954
  • Joined

  • Last visited

  • Days Won

    21

Everything posted by DZ-Jay

  1. I supposed you implemented it in Assembly Language, right? I can't see any other way to rotate bits in IntyBASIC. -dZ.
  2. No worries. It is the 8th post above. Here is the link to the thread where the solution is explained:
  3. My PRNG library above does not require any special hardware. It is in Assembly Language, true, but it includes a handy interface for IntyBASIC, and simple to follow instructions on how to integrate it into your program. dZ.
  4. I provided above a ready-made assembly language library that does it for you. Deterministic vs. non-deterministic is just a matter of adding entropy or not. Typically, you advance the PRNG during idle times, or corrupt it with some user input in order to add entropy. However, if you only advance it when you retrieve a number, then it will always follow the same sequence when starting from the same seed. I believe the IntyBASIC runtime advances the PRNG during idle loops of the WAIT statement which, depending on your program, could be non-deterministic if they are influenced by user input (i.e., if you have different code execution paths depending on user input). So that may not be ideal. dZ.
  5. I think it also depends on whether the requirement is to generate a single level terrain (which could be done during the game’s initialization), or various throughout the program’s lifecycle. If it is a single one, then I say avoid all the complexity, let the EXEC and IntyBASIC runtime seed the PRNG normally (which is deterministic), and generate the sequence prior to enabling user interaction (right after bootstrapping, before any idle loops waiting for user input). If you need a repeatable means of generating various sequences each based on their own seed, then the simplest solution appears to be to use JLP, like @cmadruga suggested. I have never used JLP for this, so I do not know what overhead is needed in order to call the API. However, I thought that enabling JLP acceleration and enhanced functions required the allocation of a chunk of System and Cartridge RAM for the code and data needed to interface between the platforms. My understanding was that it did not come for free. *shrug* dZ.
  6. Well, if you are going to use JLP, why not go the "DOOM" way and store the precomputed sequence in ROM. dZ.
  7. Somewhere in this forum, there is a library I posted for a PRNG using a Galois LSFR. It is in assembly language, though, although it includes an IntyBASIC interface. The main routine is rather compact, just a shifts and XORs. If interested, I could port it to IntyBASIC proper, although it may not be as fast. dZ.
  8. You can always do it the way the Elite guys did: implement a PRNG using a Fibonacci sequence. https://www.bbcelite.com/deep_dives/generating_random_numbers.html
  9. You could seed IntyBASIC’s PRNG with a POKE. You can find the address by looking in the listing file generated by the assembler. However, because the EXEC clears all memory during initialization, and the machine’s bootstrap sequence is deterministic, you are guaranteed to start always with the same seed. As a matter of fact, about the only way to add entropy to the IntyBASIC PRNG is to advance it during idle times and let the player’s reaction add non-deterministic delay. So, if you want a deterministic pseudo-random sequence that is always the same, just make sure to initialize your terrain before you enable any user interaction. dZ.
  10. Nice. Here are a couple of others I've made throughout the years, in case they are useful. I rather like the knight piece rendered in glorious 8-bit chunkiness. -dZ. Funny thing about that last picture, I just found the original photo I took for it, before processing it. Big difference! 😄
  11. I'm not sure I follow what you are doing there, but it seems like perhaps you are not clearing the screen between state changes. Maybe something like this would work? GameInit: ' Clear the screen before starting the level CLS ' Print here any HUD information that persists, ' like level number, score, etc. GameLoop: ' Your normal level game-play code goes here ... ' Is the level done? If (LevelDone = 1) Then Goto IntermissionInit End If Goto GameLoop IntermissionInit: ' Clear the screen CLS ' Print here any messages that will persist ... IntermissionLoop: ' Your intermission loop goes here ... ' Is the intermission done? If (IntermissionDone = 1) Then Goto GameInit End If Goto IntermissionLoop Note that the above is not real functional code, but sort of an illustration of one way of switching from game to intermission, then back again. The variables "LevelDone" and "IntermissionDone" are just proxies for whatever condition causes each of those states to end. One thing I wanted to illustrate is that any "boilerplate" details of the screen that should persist throughout an entire stage -- like the message about the current wave during the intermission -- should be printed outside the loop. That way, you only print it once, then loop to either perform a sequence, or wait for user input. In short, each stage of your game -- introduction, game-play, intermission, game-over, etc. -- should have an initialization step in which you clear the screen, set up the appropriate background scene, and initialize any special state variables to perform the work. If your initialization step is the same all the time (e.g., if all you need to do is clear the screen), then you can just do that as part of switching to the different loop. For instance: If (LevelDone = 1) Then Cls Goto IntermissionLoop End If A fancier and more structured way of performing context-switching is to use a state machine. For instance, below is an excerpt from my game engine. Notice that it relies on two state variables that control the two step machine. GamePhase: This is the broad phase of the game, like the Title Screen, the main Level Play, the Death Sequence, etc. GameState: This is the more granular state of the game -- i.e., the current step within the current game phase. In this design, the "MainLoop" does not really iterate every frame. Its job is to jump to the appropriate phase and state subroutine whenever a change of context is invoked. These subroutines are themselves the loops that iterate on every frame. Basically, the game logic itself is broken down into individual game loops that control each phase (similar to how you want to separate a "game loop" from an "intermission loop"). Within those individual game loops, certain conditions result in a change of "state" (e.g., initialization completed, or the player lost a life and we need to retry the level, etc.); and sometimes, a change of "phase" (e.g. the level or the game is over, etc.) Each of those subroutines is itself a loop. In my case, I use "DO ... UNTIL" loops, so that I can break out of them easily whenever circumstances require it. This is how my game switches modes or states: The loop continues until the state changes, at which point it returns to the "MainLoop" engine, which will then call the appropriate subroutine and engage the next phase. Below is an excerpt of the "DoPlayGame" subrioutine from the "PhasePlay" phase: That's just one way of doing things. It is my way, and perhaps not suitable to every game. Of course, there are myriad ways of organizing your game logic. The core idea I am proposing here is that you can separate your game logic into smaller contextual "loops" and control them centrally using simple variables that keep track of which state or mode your game is in. In my view, separating "state management" from "game logic" not only makes it cleaner, but it is significantly easier to troubleshoot, since the factors that control the flow of your game is limited to a small set of variables rather than spread around in various logical conditional statements throughout your game program. I hope the above offers some insight. -dZ. ---------- P.S. By the way, that "On ... Fast Goto" and "On ... Fast Gosub" illustrated above is the closest to a "Switch" or "Select Case" statement in IntyBASIC. I have adopted it throughout my programs as a means to switch conditionally between various functional options. I use it equally to control the behaviour of enemies. Below is an excerpt of my "HandleEnemy" subroutine. As illustrated in the code above, this subroutine is called on every iteration of the "DoGamePlay" loop. If any of the actions taken by the current state handler results in the enemy object changing state, the new state will be handled on the next iteration. Likewise, if any player action results in a change of state of the enemy (e.g., a player bullet hit the enemy), all we do is update the enemy's state variable and it will be automatically handled in the next frame.
  12. And here is my current Nyuundere CD collection.
  13. I really liked MazezaM, it should have been released. dZ.
  14. Got mine! Actually, I got mine a few weeks ago. I just took the time today to import them into my iTunes library and listen to them. My favourite is Thunder Soldier, with a special mention to Napoleonic Wars -- the latter's march hymns are rather well done. 👍 -dZ.
  15. Ah, right. Now I remember that. Thank you for the information. dZ.
  16. LOL! I would be quite happy to have the local university pay me to teach a course in Intellivision Programming! Hehehe. I do not know if I would be a good teacher, but it sounds like a dream job — certainly better than my current one. 😄 Good luck! dZ.
  17. Oh, it’s been a while since I loaded my CC3 with news stuff, but I just used to just copy the files to the mounted folder. Honestly, I do not recall if it supports BIN+CFG format. I assumed it did. In any case, ROM format itself does not support the metadata needed for bank-switching. dZ.
  18. Bin2Rom conversion won’t work on the CC3 if it uses bank-switching. In fact, it won’t work anywhere, since it loses the information regarding the bank usage. BIN+CFG should work. dZ.
  19. Here are a couple of general suggestions: I always put the WAIT statement at the top of the game loop. The WAIT statement induces the program to wait idly for the next frame interrupt. When the next frame arrives all graphics and sprite updates will be applied automatically by the IntyBASIC run-time. After which, your game loop should start processing the next next frame. If you put the WAIT statement at the bottom of the game loop, you are unnecessarily delaying your frame processing, because instead of starting your loop iteration immediately after the WAIT processing ends, it has to waste time jumping back to the top -- or in your case, waste even more time returning from a sub procedure before jumping back to the top. If you put the WAIT statement at the top, all that extra jumping around happens at the end of your previous frame, subsumed by the idle waiting the WAIT statement was going to do anyway. If you were to update the BACKTAB (which you do not appear to do in this program, at least not yet, but it is something to keep in mind in any case), you may want to do it as close to the WAIT statement as possible, at the top of the iteration frame. After the interrupt arrives, there is a very brief window in which the CPU has access to GRAM (graphics memory) and the STIC (video processor). This is he point at which IntyBASIC posts all changes to those resources automatically. After this brief period (called VBLANK for Vertical Blanking), the STIC will start copying the BACKTAB data, row by row, into its internal buffer to compose the next TV video frame. This means that there is a small window of time at which you can update the BACKTAB and still make it to the same video frame as your sprite and graphic updates. Making changes to the BACKTAB early after the WAIT statement ensures they are all included together. (The worst case scenario is when only part of your updates make it, which means that your screen changes are split across video frames. Depending on the complexity of the scene, this could result in "tearing" or "shearing," which is noticeable by players.) This is mostly significant when BACKTAB changes are important to game-play, like scrolling, or animating interactive elements, which ideally you would want to reflect in coordination with sprite and other graphical changes within the same video frame. Read and decode the hand-controller input as close to the WAIT statement as possible, usually right after it, at the top of the loop. Game logic is typically driven by user input, so it would make sense to try to get that as soon as possible right when your next iteration frame starts. The idea being that, once you have user input, you can spend the rest of the frame updating your game state to react to it. Update sprites using the SPRITE statement after you have updated your state variables. This follows the sequence suggested above: you WAIT for a new frame and start your loop iteration, read user input, update game state, and then update sprite records to reflect their new positions or attributes. Remember that the SPRITE and DEFINE statements only store the updates in a buffer, which will then be applied automatically when the next frame interrupt arrives (typically induced by WAIT). Therefore, there is no point or rush to call the SPRITE statements early, since they won't be reflected until the next frame. Treat your game loop as being at least one frame behind. That is, as the game world is displayed to the player, one video frame at a time, your game loop is setting the stage for the next frame. You can think of it like this: Frame N: You read user input. You update player state based on input. You update enemy state to react to player. You check for collisions. You update the game state to react to everything that has happened in this frame so far. And finally, you WAIT for the next interrupt. Frame N+1: IntyBASIC renders the video frame to the player. You read user input. You update player state based on input. ... and so on ... Anyway, these are some recommendations based on my experience. A lot of programmers (especially when starting) do not pay much attention to the order of processes or how the sausage of graphics handling in the Intellivision is made, as it were. However, if you are not careful, it could result in some weird visual glitches, which ultimately could be avoidable. I hope this offers some insight you or anybody else following. Feel free to ask any questions. dZ.
  20. A couple of things at first glance (feel free to ignore the stylistic suggestions): I see that you commented out the OPTION EXPLICIT directive (tsk! tsk!), and yet you declared all your variables with DIM anyway. I recommend you uncomment the directive to let the compiler catch errors in variables. Typos in variable names are hard to troubleshoot because the compiler will create a new variable every time it encounters a new one -- the OPTION EXPLICIT will cause the compiler to return an error if it encounters a variable which has not been declared before (like when you mistyped the name of a variable). Anyway, it is up to you, although I do not see the downside if you are aiming to declare all variables anyway. You can comment a line with an apostrophe; you do not need the REM keyword. You do not need to create compound statements with ":" -- you can put them in multiple lines or use IF/THEN/END IF blocks for legibility. IntyBASIC is a compiled language -- it compiles into assembly, not byte-code, so condensing the code gains you nothing, except perhaps a bit of eye-strain. It seems you play the song in the loop when "POINTS = 5," but nothing stops the program from calling the Play Music statement again in subsequent operations while the points are still 5. All that being said, I'll take a deeper look at the code later tonight, when I get home, and run it through the debugger. dZ.
  21. What do you mean by “If”? That game is currently in development right now.
  22. That should work, provided you change it to 2 right after testing it. Something like: MainLoop: Wait ' Check if we play music ... If (PlayMusic = 1) Then ' Do not restart music again PlayMusic = 2 ' Play the song Play MyMusic End If Goto MainLoop There is a chance that something else is wrong. It should not be. Playing music in IntyBASIC is rather straightforward. Maybe if you post your code, we will be able to pinpoint the problem. It is hard to troubleshoot in the dark. If you do not feel comfortable posting your code publicly, feel free to send a PM for assistance. dZ.
×
×
  • Create New...