ZippyRedPlumber Posted November 13, 2021 Share Posted November 13, 2021 I know I've asked this before, but how do you stitch 2 8x8 MOBs together to make a 8x16 player? Quote Link to comment Share on other sites More sharing options...
+cmadruga Posted November 13, 2021 Share Posted November 13, 2021 (edited) If those will be the same color and stacked vertically, just use DOUBLEY. That way you can use a single MOB. If not, just position the mobs with a coordinate offset. You will need to use 2 MOBs then. If you don’t have 2 MOBs available, you can still use a single one and multiplex it, but the resulting flickering effect will not look great. Edited November 13, 2021 by cmadruga 3 Quote Link to comment Share on other sites More sharing options...
Zendocon Posted November 17, 2021 Share Posted November 17, 2021 Although Auto Racing uses the EXEC, it uses 4 sprites per car. Two of those sprites are "stitched together" to create a 16x16 image, and the other two are also "stitched" to the first two for the car's shadow. In the EXEC, you can define one sprite to always be a certain pixel offset from the one before it, and every time you move the first sprite, they move together. That may or may not be duplicatable in IntyBASIC, but I'd like to know either way. It's doable in ECS BASIC, which uses the EXEC as well. 1 Quote Link to comment Share on other sites More sharing options...
carlsson Posted November 17, 2021 Share Posted November 17, 2021 I wonder how you would do that with IntyBASIC. Perhaps if you define an ON FRAME routine that knows which variables you use for sprite coordinates and position the additional/shadow sprites accordingly. It would in theory let you only manage the master sprite, but I don't know if that is a good usage of that mechanism. Of course another way would be to define a subroutine "moveSprites" that handles all sprite movement in one place, though you would still have to offset sprites by hand. Generally speaking, I think you'd figure it out quite soon. If your logic and code are structured enough so you don't scatter things around, it would be easy to achieve lining sprites next to or onto each other. State machines surely would help as opposed to knee jerk actions across the code. 2 Quote Link to comment Share on other sites More sharing options...
+DZ-Jay Posted November 18, 2021 Share Posted November 18, 2021 (edited) The sprite engine in Christmas Carol uses a similar mechanism. What the EXEC calls "linked" sprites, I called "overlay objects," because they were used primarily to add secondary colors or details to a sprite. It works something like this: When you define your logical sprites, the framework creates a record structure in RAM that includes fields for velocity, animation, position, etc. Some of it is in 8-bit RAM and some of it in 16-bit RAM, so a look-up table is then constructed with static information such as the memory pointers for the record structure, along with a hard-coded assignment to a MOB. I called each entry in that table an "Object Record" (OBJ). In terms of IntyBASIC, it would look like this: ' Define new obeject Dim #SystemRamVariables(m) Dim ScratchRamVariables(n) ' Define Object Record ' Data <sysram-pointer>, <scrram-pointer>, <mob-number> Data VarPtr #SystemRamVariables(0), VarPtr ScratchRamVariables(0), 0 Among the 8-bit RAM fields is a "Status" register, where each bit indicates something about a sprite. These are flags that indicate such things as whether the object is active, if it should be tested for collisions, if it just entered a new tile in the virtual map and is allowed to change directions, etc. -- and importantly, whether it is linked to a "parent object." For "overlays" you do a similar thing, except that the memory structures are slightly different (in an effort to conserve RAM, since overlays lack their own velocity and position, etc.). However, this need not be so, and in fact, I believe that the EXEC allows any object to be linked with every other, so their memory commitments are uniform for all sprites. The key is that the overlays include a field with the "Object Record" index of their parent object, and an optional X and Y position offset from it. The offsets are encoded as two nybbles in a single byte (again, to conserve RAM). The overlays are then added to a similar table with static pointers, following the one for the regular objects, forming essentially one long table for both kinds of objects. These entries I called "Non-Interactive Object Records" (NIOBJ), which in my head I pronounce just like the name "Niobe." Fun Fact: I called them "non-interactive" because they are the same objects I used for software sprites and other elements that do not move on the screen. Apart from the overlays of the regular sprites, they are also mostly used for static graphical animation elements like snowflakes, droplets, presents, the jack-in-the-box, etc. In any case, their link to a parent is therefore optional, dynamic, and depends on the need at the moment. Ultimately, these records are used by the sprite motion and animation engines, which run on every frame. Because the OBJ and NIOBJ record structures are identical, and because the RAM layout is similar (a NIOBJ has a subset of the fields of an OBJ) the animation engine can just iterate through both tables as one, deference the pointers as necessary, and perform the animation accordingly. The sprite motion engine is a bit more discriminating. It too runs through both tables as one, but it tests the "is linked to parent" flag, and if it is true (and assuming that the object is an NIOBJ), it will dereference the parent index and use its current position as the position of the NIOBJ, adjusted by the offset accordingly. In terms of IntyBASIC, it would look something like this: ' Move all objects For I = 0 to TotalObjectCount ' Get Object Record Obj = ObjectTable(I) ' Get 8-Bit RAM memory structure Rec = Obj(FLD_SCRATCH_RAM) ' Get parent position if its linked If (Rec(FLD_STATUS) And LINKED_TO_PARENT) Then ' Get parent object ParentObj = ObjectTable( Rec(FLD_PARENT) ) ' Get parent record ParentRec = ParentObject(FLD_SCRATCH_RAM) X = ParentRec(X_POS) + Rec(X_OFFSET) Y = ParentRec(Y_POS) + Rec(Y_OFFSET) Else X = Rec(X_POS) Y = Rec(Y_POS) End If ' Update MOB with new position #MobShadow(X_REGISTER + Rec(MOB_NUMBER)) = X #MobShadow(Y_REGISTER + Rec(MOB_NUMBER)) = Y Next (Note that this is untested code, straight out of my head, so consider it like pseudo-code.) All that indirection was necessary in my game to abstract the sub-systems and allow for a flexible framework. It was also hyper-optimized in tight assembly language in order to reduce memory access and expensive computations. For an IntyBASIC game all that abstraction may not be needed, so a more straightforward solution could be employed. Lookup tables and tight memory structures may still apply. dZ. Edited November 19, 2021 by DZ-Jay 1 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.