It's a little bit distracting, but not the worst. There's no way to make it a slightly lighter shade of gray? Smile
I would stick it in the upper right hand corner. Personally thing it would fit nicely up there.
Cannot make the gray any lighter without some questionable edits. I moved the portrait to the suggested location. How is it now?
Good call to geekboy; I like it much better there. Smile
Added most of the menus and put in placeholders for replay and external levels section. I need to verify that character selection passes along the correct data, and then I can start working on the shooter part of the game.

I intend on redoing the right side of the screen where the stats are displayed, more or less because there's extra stuff I wanted to throw in there. There's also a display problem that happens on some calcs that I need to address.

Added in the score counter as long as an (unused at the moment) kills counter. The player is able to move around on the field. There is a single black line in the middle of the field to serve as a test for collision detection, which works, but I have not yet removed that.

Also, the score display will display in hexadecimal (zero-padded to maintain length) if set from the menu options. This was originally designed to help me debug the game since the score counter is a perfect way to output values as the game runs. It's also a good way for the user to see through the cheap methods that I'll employ to make the score counter count upward at regular intervals.

Next on the todo list: Resource allocation for additional menus and backgrounds. Also have to do some sort of scripting and I've also got to reconstruct the bullet engine.

In the following screenshot, the scoring, hex mode, and movement is demonstrated. The score panel is not actually tied to the score, but is instead tied to the some of the internal game timer. This "some" part is seen clearly when the score is viewed under hex mode.



EDIT: May have to redo the bullet engine code from scratch. To many any necessary upgrades, the preexisting code just simply won't work. For any bullets larger than 2x2, the lack of clipping on the left/bottom edges of the screen would become too noticeable. I haven't figured out a solution to this problem yet but I think it might involve messing around with how I'm storing the coordinates for each bullet.
I very heartily support hexadecimal scoring; I'm happy you added this. Smile I'm also quite please to see that you're taking up CaDan again, although I'm slightly saddened that your other impressive grayscale RPG project is no longer on your front burner.
I'm half-tempted to start up E:SoR again. A few weeks ago, I started up my trusty TI-84+SE and played what I had of that game before I restarted it. I'm somewhat disappointed with the fact that it had to be restarted so far into the project. I mean, when I played it for the first time in a few months, I got the feel that it was *almost* done and what was there at the moment amounted to a nearly complete game. I'm tempted to simply copy and paste all the really "hard" stuff that I wrote in the previous version, including those nightmarish battle calculations and victory routines. Believe me, after having been stuck on that run of code for a few weeks, I started questioning Zera as to why he didn't go with a more traditional EXP system. The simple answer was that he wanted something different, but the further I worked the proficiency gains part of the code, the more I realize *why* people coded EXP. It was SIMPLE.

Anyway, back to CaDan, (since this is what the topic is supposed to be about) the plan is to rework the bullet engine and put forth a few test conditions similar to how CaDan was in its early days of development. Bullets flying out of nowhere and you, the player, having to dodge them all for as long as possible. Not much of a game at that stage but it's a valuable test of the engine. Among the things that will be tested is the planned slowmode which reduces the game's speed to half and doubles the bullet table's size.

After that is done, I plan on putting together danmaku-mode menus (pause) and a proper way to exit the game so that after you have lost/quit/"won". This includes high score entry and saving replay files.
After spending some serious time slacking off or reading the Temeraire series, I'm back to coding CaDan. Not much has changed since I last posted other than my intent on getting the bullet engine recoded.

Some of the old engine will be copied and pasted (ray drawing routine) but I'm going to redo the way normal bullets are rendered and moved. The plan is to include more than just pixel-sized and 2x2 size bullets, and the former scheme did not allow it without some serious clipping problems.

Next post I will make will be a screenshot of the bullet engine working to some degree.

EDIT: No. Bullet system not interesting. Building the script system so I can test the bullet system is more interesting so far. I have encoded a number of general purpose commands. I haven't completed the list but it is well enough along to feel good about it. Now, that's not saying much, but still. I've got a piece of the script spec so you guys can see it. Not sure if I've already posted it but I did do a little updating on it. Tell me what I'm missing from the general purpose section (there will be a boss and stage section. Not specified yet).


Code:
Script system outline:

Internal notes:
Warning: Do not use the following for names of a script system command
"db", "dw", "end", "org", "byte", "word", "fill", "block", "addinstr",
"echo", "error", "list", "nolist", "equ", "show", "option", "seek"
These are reserved by SPASM

Naming conventions:
 rx = virtual register 0-7
 nn = 1 byte value
 ww = 2 byte value
 b  = Some value between 0-7
 s  = Some value between 0-15
 
Some names will have a more descriptive label for its use. If one is used,
read the description to determine the data's size.
 
VERY IMPORTANT NOTE: ALL SCRIPT NAMES HAVE A PERIOD (.) PRECEDING THE NAMES
EVEN THOUGH THEY DO NOT SHOW IN THIS LIST. ALWAYS REMEMBER.

COMMANDSET AND NAME
==============================================================================
------------------------------------------------------------------------------
- NORMAL EVERYDAY USE --------------------------------------------------------
------------------------------------------------------------------------------
000             | No operation. The script system halts on encountering this.
 NOP            | Used for filler or something.
------------------------------------------------------------------------------
001-008         | LOAD(rx,nn)
 LOAD           | Stores a constant (1 byte) into a register.
 2 bytes        |
------------------------------------------------------------------------------
009-016         | ADD(rx,nn)
 ADD            | Adds a constant (1 byte) with a register, then stores the
 2 bytes        | results back to the register. Affects zero and carry flags.
                | There's no subtract operand for this mode. Use a negative
                | constant for doing that. There is no add with carry.
------------------------------------------------------------------------------
017-024         | CLEAR(rx)
 CLEAR          | Sets a register to zero.
 1 byte         |
------------------------------------------------------------------------------
025-032         | AND(rx,nn)
 AND            | Do a bitwise AND operation between a register and a constant
 2 bytes        | and store the result back into the register.
                | Affects the zero flag. Does not affect the carry flag.
------------------------------------------------------------------------------
033-040         | XOR(rx,nn)
 XOR            | Do a bitwise XOR operation between a register and a constant
 2 bytes        | and store the result back into the register.
                | Affects the zero flag. Does not affect the carry flag.
------------------------------------------------------------------------------
041-048         | OR(rx,nn)
 OR             | Do a bitwise OR operation between a register and a constant
 2 bytes        | and store the result back into the register.
                | Affects the zero flag. Does not affect the carry flag.
------------------------------------------------------------------------------
049-056         | CPL(rx)
 CPL            | Inverts all bits in a register.
 1 byte         | Affects the zero flag.
                | If you want to do NEG instead, just CPL, then INC it.
------------------------------------------------------------------------------
057-064         | WAIT(rx)
 WAIT           | Makes the script system wait for the number of game cycles
 1 byte         | that is stored in a register. Remember that 24 cycles is
                | about one second's worth of time in normal gameplay mode.
                | You should be setting that register to some known value
                | before using this instruction. Feeding in 0 is using 256.
------------------------------------------------------------------------------
065-072         | CMP(rx,nn)
 CMP            | Performs subtraction between a register and a constant in
 2 bytes        | the form: register-constant. The result is NOT stored back,
                | but instead, used to affect the zero and carry flags.     
                | Good for use with conditional jumps.
------------------------------------------------------------------------------
073-080         | TEST(rx,nn)
 TEST           | Performs a bitwise AND operation between a register and a
 2 bytes        | constant, but does NOT store the results back to the
                | register. Instead, it's used to affect the zero flag.
                | Used when you need to figure out which bits are set in a
                | register, perhaps for conditional jumps?
------------------------------------------------------------------------------
081-088         | TRACK(rx)
 TRACK          | Output-only. Sets the given register to an angle that would,
 1 byte         | when used with the SHOOT command, fire a bullet directly
                | toward the player.
------------------------------------------------------------------------------
089-096         | SHOOT(rx)
 SHOOT          | Fires a shot at the angle given in a register. 'nuff said.
 1 byte         |
------------------------------------------------------------------------------
097-104         | SETSTATS(rx,nn)
 SETSTATS       | Stores rx to an external variable. If you need to define
 2 bytes        | your own variables, look in the code developer's guide for
                | more information.
------------------------------------------------------------------------------
105-112         | GETSTATS(rx,nn)
 GETSTATS       | Retrieves rx from an external variable. Again, if you need
 2 bytes        | to define your own variables, look in the code developer's
                | guide for more information.
------------------------------------------------------------------------------
113-120         | MULT(rx,nn)
 MULT           | Multiplies a register by a constant, then stores the least
 2 bytes        | significant byte (LSB) of the result back into the register.
                | NOTE: If it's possible, try to use the rotate/shift
                |       commands if you're dividing or multiplying by
                |       multiples of 2. It's much friendlier that way.
                | The most significant byte (MSB) is stored in "sta.overflow"
                | be accessed by the getstats command. Flags are affected as
                | follows: Carry is set if the MSB is not zero. Zero is set if
                | the result in the LSB was zero (even if the whole isn't)
------------------------------------------------------------------------------
121-128         | DIVIDE(rx,nn)
 DIVIDE         | Dividend (rx) / Divisor (nn) -> Quotient to (rx)
 2 bytes        | This is a slow operation. See if you can't use right shifts
                | instead.
                | The remainder is stored in "sta.overflow", which is accessed
                | via getstats command. Flags are affected as follows:
                | Carry is set if there is a remainder. Zero is set if the
                | quotient is zero (does not check remainder).
                |
------------------------------------------------------------------------------
129-136         | INC(rx)
 INC            | Increments rx by one. Same as ADD(rx,1) but much faster and
 1 byte         | uses less memory. Affects only the zero flag, to remain
                | consistent with how the Z80 does things.
------------------------------------------------------------------------------
137-144         | DEC(rx)
 DEC            | Decrements rx by one. Same as ADD(rx,-1) but much faster and
 1 byte         | uses less memory. Affects only the zero flag, to remain
                | consistent with how the Z80 does things.
------------------------------------------------------------------------------
145-152         | DJNZ(rx,label)
 DJNZ           | Automatically decrements the given register and takes the
 2 bytes        | specified relative jump while the register does not become
                | zero that cycle. Just like Z80's djnz instruction, except
                | you can use any register.
------------------------------------------------------------------------------
------------------------------------------------------------------------------
153             | MOVE(rxa,rxb)
 MOVE           | Copies the contents of register B over to register A.
 2 bytes        | Register A is overwritten with B and B stays the same.
------------------------------------------------------------------------------
154             | SWAP(rxa,rxb)
 SWAP           | The values in register A and register B are swapped.
 2 bytes        | Nothing is destroyed in this operation.
------------------------------------------------------------------------------
155             | ADDRX(rxa,rxb)
 ADDRX          | Adds register A and register B, then stores the result
 2 bytes        | back into register A. Affects only the carry flag.
------------------------------------------------------------------------------
156             | SUBRX(rxa,rxb)
 SUBRX          | Subtracts register B from register A in the form of
 2 bytes        | rxa-rxb, then stores the result back into register A.
                | Affects
                |
                |
------------------------------------------------------------------------------
157             | ROTR(rx,b) / ROTL(rx,b)
 ROTR/ROTL      | Rotates a given register a number of bits right or left
 2 bytes        | (respectively). All bits that leave one side of the register
                | Immediately appears on the other side of the register.
                | Flags are NOT affected.
                | INTERNAL NOTE: Distinguishing between ROTR and ROTL is done
                |                with bit 7 of the data byte. (1=ROTL)
------------------------------------------------------------------------------
158             | SHIFTR(rx,b) / SHIFTL(rx,b)
 SHIFTR/SHIFTL  | Shifts a given register a number of bits right or left
 2 bytes        | (respectively. All bits that leave are gone forever. Bits
                | shifted in will always be zero.
                | Flags are NOT affected.
                | INTERNAL NOTE: Distinguishing between ROTR and ROTL is done
                |                with bit 7 of the data byte. (1=SHIFTL)
------------------------------------------------------------------------------
159             | MULTRX(rxa,rxb)
 MULTRX         | Multiplies register A with register B, then stores the
 2 bytes        | LSB of the result back to register A.
------------------------------------------------------------------------------
160             | DIVIDERX(rxa,rxb)
 DIVIDERX       | Divides register A with register B in the form of rxa/rxb,
 2 bytes        | then stores the quotient to register A.
------------------------------------------------------------------------------
161             | ANDRX(rxa,rxb)
 ANDRX          | Performs the bitwise AND function between register A and
 2 bytes        | register B, then stores the result to register A. Affects
                | the zero flag.
------------------------------------------------------------------------------
162             | ORRX(rxa,rxb)
 ORRX           | Performs the bitwise OR function between register A and
 2 bytes        | register B, then stores the result to register A. Affects
                | the zero flag.
------------------------------------------------------------------------------
163             | XORX(rxa,rxb)
 XORRX          | Performs the bitwise XOR function between register A and
 2 bytes        | register B, then stores the result to register A. Affects
                | the zero flag.
------------------------------------------------------------------------------
164             | CMPRX(rxa,rxb)
 CMPRX          | Performs virtual subtraction between register A and register
 2 bytes        | B. Does NOT store the result anywhere, but the carry and
                | zero flags are affected as though subtraction took place.
                | Useful for testing conditions.
------------------------------------------------------------------------------
165             | TEXTRX(rxa,rxb)
 TESTRX         | Performs a virtual AND function between register A and
 2 bytes        | register B. Does NOT store the result anywhere, but the
                | zero flag is affected as though an AND function was done.
                | Useful for testing bits to see if they're set.
------------------------------------------------------------------------------
166             | JUMPNC(label) [+ or - 127 bytes in either direction]
 JUMPNC         | Sets the script's execution pointer to wherever you defined
 2 bytes        | the label only if the result of flag altering command prior
                | to this instruction stayed between 0 and 255 (carry flag
                | reset)
------------------------------------------------------------------------------
167             | JUMPC(label) [+ or - 127 bytes in either direction]
 JUMPC          | Sets the script's execution pointer to wherever you defined
 2 bytes        | the label only if the result of flag altering command prior
                | to this instruction crossed zero. (Carry flag set)
------------------------------------------------------------------------------
168             | JUMPNZ(label) [+ or - 127 bytes in either direction]
 JUMPNZ         | Sets the script's execution pointer to wherever you defined
 2 bytes        | the label only if the result of flag altering command prior
                | to this instruction was NOT zero. (Zero flag reset)
------------------------------------------------------------------------------
169             | JUMPZ(label) [+ or - 127 bytes in either direction]
 JUMPZ          | Sets the script's execution pointer to wherever you defined
 2 bytes        | the label only if the result of flag altering command prior
                | to this instruction was zero. (Zero flag set)
------------------------------------------------------------------------------
170             | JUMP(label) [+ or - 127 bytes in either direction]
 JUMP           | Unconditionally sets the script's execution pointer to
 2 bytes        | wherever the label is defined. Just like Z80's JR.
------------------------------------------------------------------------------
171             | NEWPOSRT(rx_angle,rx_radius)
 NEWPOSRT       | Changes the firing position from the center of the enemy to
 3 bytes        | radius away from that center at some angle, both of which
                | are stored in registers. ANGLE is between 0 and 255, and
                | RADIUS can be anything, just note that 90 is the length of
                | the longest possible line on the screen. Keep that in mind
                | so you don't clip.
                | NOTE: Position is reset to center after a pause, or another
                |       use of the NEWPOSRT command.
------------------------------------------------------------------------------
172             | NEWPOSXY(rx_x,rx_y)
 NEWPOSXY       | Changes the firing position from the center of the enemy to
 3 bytes        | some offset X,Y away from the enemy. You MUST understand
                | that Y is reversed (positive values move down, negative
                | moves upward). To obtain negative values of a certain number
                | you should CPL/INC it. Or store a negative number to the
                | register to begin with. The screen is 64 by 64 pixels.
                | NOTE: Position is reset to center after a pause, or another
                |       use of the NEWPOSRT command.
------------------------------------------------------------------------------
173             | USESPRITE(rx_resourceID,rx_locationID)
 SETSPRITE      | Sets a sprite found in resourceID to an active enemy sprite
 3 bytes        | found in locationID. resourceID refers to a place on the
                | current script's resource table, which should be set at
                | "codegen"-time. locationID refers to a number 0-3, which
                | refers to which sprite slot to use (there are four).
------------------------------------------------------------------------------
174             | JUMPTABLE(rx_offset,nn_table_length) \.db label1,label2,...
 JUMPTABLE      | Allows you branch to different routines depending on what
 3+n bytes      | is in a register. You MUST put the table immediately after
                | this instruction. Example:
                |
                | LOAD(r1,0)      ;sets r1 to zero
                | JUMPTABLE(r1,4) ;r1 is the offset, 4 is the number of labels
                | .db Label_0     ;<-- Will be chosen, since it's the 0th one.
                | .db Label_1     ;Next label. If r1=1, then this is taken.
                | .db Label_2     ;Same, except if r1=2...
                | .db Label_3     ;And again... If r1=3...
                |
                | Note: If r1 is a value outside the bounds, the table is
                |       skipped over and code beneath is will run.
                | Note: The labels are relative addresses, + or - 127 bytes
                |       in either direction. This makes it prohibitive to use
                |       very large tables. If you need to make tables that
                |       large, use jump nodes as intermediaries.
                | IMPORTANT NOTE: THE TABLE CANNOT BE LARGER THAN 16 LABELS!
                |                 If you try to make it larger anyway, garden
                |                 gnomes will (likely) invade your home.
                | A typical use for this routine is retrieving the built-in
                | difficulty level, and then branching to different attacks
                | based on the difficulty, so one script does many things.
                | See how *you* can abuse this sucker. I won't be stopping you
------------------------------------------------------------------------------
175             | CALL(ww_relativelabel)
 CALL           | Lets you run a subroutine so you can save precious space by
 3 bytes        | not having to replicate redudnant code. The spacing for this
                | label is double-wide, so it can reach anywhere you need it
                | to. DO NOT TRY TO CALL ANYTHING WHILE IN A SUBROUTINE.
                | Endless loops and never getting back to the main code will
                | result. It's safe this time around to do a PAUSE or a WAIT
                | while you're in a subroutine, however. It's safe this time
                | around to do a PAUSE/WAIT combination while in a subroutine.
------------------------------------------------------------------------------
176             | RETURN   
 RETURN         | Exits a subroutine. Don't try to use this if you're not in
 1 byte         | a subroutine. Main script code all have exit points, and
                | using this command is NOT one of them. You might end up
                | crashing your calc or something.
------------------------------------------------------------------------------
177             | XYTORT(rxa_x,rxb_y,rxc_r,rxd_t)
 XYTORT         | Takes of the x,y coordinates found in registers A and B
 3 bytes        | (respectively), then uses the position given by the center
                | of the enemy in use (or whereever newposxy/newposrt has
                | changed it to) to output a distance and an angle in
                | registers C and D, respectively.
------------------------------------------------------------------------------
178             | RTTOXY(rxa_r,rxb_t,rxc_x,rxd_y)
 RTTOXY         | Similar to above, except it takes a distance and an angle,
 3 bytes        | then converts it to its corresponding x,y coordinates,
                | outputting to registers C and D, respectively.
                | The starting position is the center of the enemy in use or
                | wherever you changed it to via newposxy/newposrt.
                |
------------------------------------------------------------------------------
179             | GETPLAYERXY(rxa_x,rxb_y)
 GETPLAYERXY    | Outputs the player's X,Y coordinates to registers A and B,
 2 bytes        | respectively. If you only need an angle, you should be using
                | the TRACK command instead. Much faster that way.


Another EDIT: Bullet system all of a sudden became VERY interesting. Interesting because it WON'T WORK. Something about used bullets not being recycled and the bullet allocation table not being properly handled. More details on this when I actually fix the problem.
Got the bullet table handling routines to work right. Wrote a script to test out the patterns I can make on a simple downward-moving bullet. Result:

The radial movement is 3 degrees (of 256) per game cycle. The script varies the distance from the center to where the bullets are generated.
Quadruple-post. Sorry guys, I couldn't wait another month to update this one.

Minor victory: Shooting is enabled. Also, CaDan is in debug mode so you can't get hit.



ToDo: Codify enemy structures and allow collisions between your bullets and soft, fleshy enemies. I don't have a good sprite routine down, so I may have to run tests blind. Which isn't a bad thing, really. It works if bullets start disappearing mid-flight. Might also want to start coding in a way to create and destroy enemies. Oh, and some manner of getting them to move. Movement is supposed to be an inherent thing but I don't have a script type set up for stuff like that yet.

Meta: So if no one replies this time around, I guess I'll be shooting for the coveted quintuple-post?
This time around, I pulled together a mini menu thing so you can pause CaDan and select from one of a few options. At the moment, only the "Go Back" and "Quit Game" menu options are enabled. Also, measures have been taken to help reduce pause spamming, mostly in the requirement that all keys need to be released before the menu will accept any key presses.



The next order of business will either be working on the resource table structures, or putting together a high score screen. For the purposes of high scores, quitting a game is handled the same as a game over, so you will be able to save a high score that way, but hitting ON while playing the game is treated as a quick exit (nothing is saved).

Also, Geekboy is working on the shot type for the dragon character. So far, he's got the fire breath down, but he's still working on the claw wave attack. Expect more soon.

EDIT: Modified screenshot to include a white backing on the menu title. It was getting difficult to see what was there. At least with the menu options, they can be moved to see what it reads.
How have I missed all of these update posts? That's looking so awesome. How many pages is the app, and how full is the app inside those pages? I appreciated that you and Geekboy always make good use of our HCWP sessions for collaborating on coding. Smile
CaDan is three app pages large.
Page 1: 4665 bytes free
Page 2: 7839 bytes free
Page 3: Totally empty.

More menus, including the high score naming and replay file naming, along with replay file selection and external level selection has to be put into page 1.
The rest of the script system needs to be coded, which is quite a few commands. I also have to put together just about every other graphical aspect onto page 2.
Page 3 is being reserved for stage data and graphics. The whole thing is going to be graphics heavy, so I'm not sure that a whole app page is going to be enough. I'm hoping to set it up so that I can just extend into a 4th page as the game grows, if necessary.

Also I neglected to mention between the next to last and last post that I finished up enemy collisions and their ability to hold to a script. Still need to codify some sort of movement path for them. Oh, yes. And we have way too many sprite routines in CaDan for our own good now.

EDIT: And yet we're just shy one sprite routine needed to pull everything together. Not that it matters much since there's workarounds for everything. Like multiple invocations of the 8x8 sprite routine to form up something larger.
Thanks for the extra information. Smile I see it's been over two months since I last heard from you about this, and Geekboy nagged me that I had been ignoring the project, so I shall poke it again. I understand that he's wading through some of his code to document it. Do you have so many sprite routines to avoid having a lot of conditions in your routines to slow them down? Or do they do very disparate things?
KermMartian wrote:
I see it's been over two months since I last heard from you about this


Actually we have been updating the omnimaga topic a wee bit more than here and quite a few updates have been made. And if you actually joined us on hcwp nights back then you would have know about some of the updates P:

But I will work on getting this topic up to par at least screenshot wise.




feel free to ask what ever you want about those screen shots ill do my best to explain then if you want.

I am just linking this post because its huge. iambian documented alot of how the angle calculations for our bullet routines work. Very technical read but pretty awesome at the same time
http://ourl.ca/2637/259132
So here is an update.

New look for the dragons fire.




...and that's about it. everything else that was updated was done internally and honestly has no visual representation of it...

To sum up what changed. We reworked the bullet table and its handling routines we changed how player bullets are stored and interacted with to make them easier to work with on my end.

We started a resource table design based around a concept of garbage collection. This is because deleting assets immediately can cause a minor amount of lag that could cause issues. with a GC we can mark it as removed and it will be collapsed as needed/as time goes on so that there is no lag.

And that's about it. More to come soon going to keep over here updated just not going to spam it as much as omnimagas topic!

This is the new code repository where you can see our changes(and lack of sense on how to use mercurial) and follow along with development or see the code and go insane your choice Razz
https://bitbucket.org/CFD_LLC/cadan/
  
Register to Join the Conversation
Have your own thoughts to add to this or any other topic? Want to ask a question, offer a suggestion, share your own programs and projects, upload a file to the file archives, get help with calculator and computer programming, or simply chat with like-minded coders and tech and calculator enthusiasts via the site-wide AJAX SAX widget? Registration for a free Cemetech account only takes a minute.

» Go to Registration page
Page 3 of 3
» All times are UTC - 5 Hours
 
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum

 

Advertisement