Jump to content
IGNORED

Castlevania for Intellivision - actual gameplay


Rev

Recommended Posts

It did not take long before hitting that 16kb mark which I had thought would have ended development. It was not until finding that 42k demo in the Contrib folder that helped overcome that. I can't imagine that taking too long to reach though once level maps are a more reasonable length. Is there a different technique required to get to 84kb?

The 42k demo is calculated as words. That's 84 kilobytes.

Link to comment
Share on other sites

I was contemplating using backtab for candles, among other things possibly. I was also redefining sprites for things like the whip animation (3 frames), that way I am not just occupying cards, but not sure if it is worth the potential performance hit. I was doing the same for the character animation, but instead just stored 16 cards for the three animation frames and kneeling graphics to hopefully improve overall performance. I figure even for that I could refine some of those for stair animation and getting hit, but have not attempted that yet.

 

Without music things seemed to run at a consistent 60 frames per second with up to 4 enemies / projectiles using hardware sprite collision. However when I add music and have 2 enemies on the screen, the performance drops substantially. This has made me reconsider if I should focus on adding secondary weapons and all the other things that make Castlevania feel like Castlevania.

 

I am happy to see that I should be good on space. 84kb is a long ways away!

Link to comment
Share on other sites

You need to optimize your code. I've saw your Youtube video.

 

Currently IntyBASIC doesn't support short-circuit evaluations, so using AND and OR is heavy processor-wise.

 

For example, in an imaginary game:

 

IF enemy_x > 50 AND enemy_attack > 80 AND enemy_active THEN
END IF
Would be faster this way:

 

IF enemy_active THEN
    IF enemy_attack > 80 THEN
        IF enemy_x > 50 THEN
        END IF
    END IF
END IF
Try to not repeat comparisons, if you use enemy_type continuously, it would be best optimized as:

 

    ON enemy_type(x) GOTO enemy_inactive, enemy_1, enemy_2
  • Like 3
Link to comment
Share on other sites

I was wondering if having GOSUBs or GOTOs would be faster, but in my mind jumping forward and backward sounded more intensive. Of course, I have no understanding of what is happening on the back end. I have been trying to find different ways to reduce the overhead from the program since posting that video. Doing things like skipping specific logic entirely when on stairs, or while jumping, not to mention replacing redundant calculations with individual variables that store the calculation once. I see there is a ways to go though.

 

Currently I do something very similar to your example with each enemy type (If enemy_type = 1, = 2, = 3, etc). Naturally each enemy needs separate logic, so I was not sure if having an ON enemy_type GOTO , versus having them in separate IF statements. Being inside of a loop, I was not sure if using GOSUB would cause any issues or not.

 

I appreciate the insight and will continue to work towards better program efficiency.

  • Like 1
Link to comment
Share on other sites

I was contemplating using backtab for candles, among other things possibly. I was also redefining sprites for things like the whip animation (3 frames), that way I am not just occupying cards, but not sure if it is worth the potential performance hit. I was doing the same for the character animation, but instead just stored 16 cards for the three animation frames and kneeling graphics to hopefully improve overall performance. I figure even for that I could refine some of those for stair animation and getting hit, but have not attempted that yet.

 

Without music things seemed to run at a consistent 60 frames per second with up to 4 enemies / projectiles using hardware sprite collision. However when I add music and have 2 enemies on the screen, the performance drops substantially. This has made me reconsider if I should focus on adding secondary weapons and all the other things that make Castlevania feel like Castlevania.

 

I am happy to see that I should be good on space. 84kb is a long ways away!

 

Personally, I recommend allocating 1 or 2 GRAM cards for animations (depending on the vertical resolution of your sprites), and cycling them in place at the animation rate. That way you free up GRAM for additional details. Most games do this effectively without incurring a severe performance penalty.

 

It can be even more effective if you are selective with your GRAM updates and only copy "dirty" animation cards. That's what I do in my game and it allows me to animate over 12 individual objects at a time (the maximum used in my game; I did not test the actual upper limit). Applying different animation rates to each (or staggering their animation execution) will result in very few of those objects coinciding in an update at the same time.

 

For instance, animating two objects at 30 Hz will result in them updating at the same time every other frame. If I start one on an odd frame and the other on an even frame, they will alternate updating on every frame. I use fractional frame-rates and typically apply different values to each object, so the chances of convergence is even less.

 

-dZ.

Link to comment
Share on other sites

I was wondering if having GOSUBs or GOTOs would be faster, but in my mind jumping forward and backward sounded more intensive. Of course, I have no understanding of what is happening on the back end. I have been trying to find different ways to reduce the overhead from the program since posting that video. Doing things like skipping specific logic entirely when on stairs, or while jumping, not to mention replacing redundant calculations with individual variables that store the calculation once. I see there is a ways to go though.

 

Currently I do something very similar to your example with each enemy type (If enemy_type = 1, = 2, = 3, etc). Naturally each enemy needs separate logic, so I was not sure if having an ON enemy_type GOTO , versus having them in separate IF statements. Being inside of a loop, I was not sure if using GOSUB would cause any issues or not.

 

I appreciate the insight and will continue to work towards better program efficiency.

 

The "ON enemy_type GOTO/GOSUB" statement compiles into a simple dispatch table, sort of like a "switch" statement in C or a "Select Case" in Visual Basic. The test is performed once and results in an address offset or table entry to which the program flow will jump. This is why the values are expected to be in sequential order. ;)

 

In contrast, multiple "IF...ELSE" statement will result in individual tests for conditions for each one.

 

Therefore, if your enemy types are numeric (which they are), and they are sequential (which they appear to be), then you're better off using the "ON ... GOTO/GOSUB" statement. (Note that if they are "one-based" instead of "zero-based," you'll need to adjust the value in the expression, like "ON enemy_type - 1 GOSUB...", since the jump table is zero-based.)

 

As for your other question, GOSUB (a jump to subroutine) is effectively the same as GOTO (an unconditional branch), except that it tracks the return address and returns to it upon completion. A GOSUB (JSR) is slightly more expensive than a GOTO (B) by a mere couple of cycles (actually 3), but only if are counting specifically and exclusively the jump point. If your GOTO target needs to figure out what to do on its own in order to return control to an applicable point, then you're losing out against the GOSUB.

 

In other words, if your entry and return points are static, it is slightly faster to just GOTO a sub-routine and GOTO another place afterwards.

 

However, all that said, you must consider if the loss of structured program flow control incurred by "spaghetti code" is worth the effort. Are those 3 cycles going to buy you back more performance than, say, coming up with a better algorithm to move your enemies, or an improved animation engine?

 

I know that back in the day, that's how we all learned to program -- I certainly did -- but once I learned about "structured programming," it was GOSUBs all the way, and I never looked back. Today, I only use static call chaining with unconditional branches as a last resort, when all my other options for optimizations are exhausted. It's a b*tch to reason through a convoluted "spaghetti" code flow, and a pain to troubleshoot. ;)

 

-dZ.

Edited by DZ-Jay
Link to comment
Share on other sites

 

That's direct access, but with memory banking/paging can't you have an Intellivision cartridge with hundreds of k-words?

That wasn't the point. The original poster confused 42K as "Kilobytes," which is common In other platforms communities. On the Intellivision, the limits stated as "K" more often than not mean "Kilowords," so double the byte size.

 

The poster seemed concerned that his program was reaching "42K" but in reality, his ROM file size was in Kilobytes, so just half of what he thought in 16-but words.

Link to comment
Share on other sites

Yes. Easily another 120 kwords with two 4k switchable pages.

Well, actually, not quite so "easily," since the banks are effectively mutually exclusive. That means planning and coordination and proper separation of code and data to be able to distribute them effectively throughout the game phases. ;)

 

Yes, it's a lot of ROM space, but converting a large program to use bank switching requires some amount of effort if it hasn't been designed before with that in mind.

 

It may not be too difficult, but it doesn't come for free either. It also binds the code to either jzIntv, or a JLP-based cartridge board. That may not be a problem at all, but it needs to be understood.

 

dZ.

Link to comment
Share on other sites

Well, actually, not quite so "easily," since the banks are effectively mutually exclusive. That means planning and coordination and proper separation of code and data to be able to distribute them effectively throughout the game phases. ;)

 

These aren't exclusive with JLP-Flash as far as I know. Both banks can map their own set of 60K words.

Link to comment
Share on other sites

These aren't exclusive with JLP-Flash as far as I know. Both banks can map their own set of 60K words.

I believe that you need support for it in the firmware, and I am not sure that other PCBs have it.

 

I think the CC3 and Intellicart do, but I'm not sure. Also there may be different implementations of it.

 

I could be wrong, but that was my understanding. Perhaps intvnut can provide some clarity...

 

dZ.

Link to comment
Share on other sites

  • 2 months later...

Skywaffle, coming from a Castlevania fan, I have to say... amazing job!!!

 

I super enjoyed your video and thought it was great to see one of my most favorite games of all time on Intellivision..

 

Thanks for the update I have been following your progress and I am looking forward to seeing more.

Link to comment
Share on other sites

Hello again,

 

For anyone that may be interested; I have posted an updated video showing some of the progress for the game I have been working on. There is a lot to do, but I felt that it was shaping up a bit over the past few months.

 

https://youtu.be/qD1VROfOuB8

Very cool!!

 

Some thoughts:

 

I think changing Simon's color to red when he's low on health would help let the player know how much health he has. And you can display the boss's health on screen using tiles since the screen isn't moving anymore.

 

I would suggest getting Jzintv emulator and a front end. Nostagia is less accurate than jzintv and my 42K mapped game won't boot in Nostagia. Jzintv does have built in video recording, you can press Win-A to record your gameplay to an AVI file. The downside, uploading to Youtube will drop the framerate to 30fps(because it's not 720p),loosing the multiplex'd frame.

 

The game is shaping up really well, keep up the wonderful work!

Link to comment
Share on other sites

For the video I just tried to use the Nostalgia emulator. The framerate seems to be a little better on this old laptop, and you can easily map a controller. However for all my testing, I use JZIntv, it is a lot more convenient to load the game quickly. In fact I just use a batch file to compile, assemble, and run my intybasic programs on JZintv.

I may try using the video recording option next time, although I will have to see how much it affects the video, there is a bit of multiplexing and sprite colors changing on odd/even frames.

 

Right now I am using all the memory locations mentioned in the 42k sample file, although I am only using just over 36k. I still need to create bitmaps and level data for the last stage, as well as more routines for enemies / bosses.

I have wondered about altering Simon's color based on his health, or maybe have his outline flash a color. Whenever he takes damage, his health is displayed on the screen briefly. Another idea was maybe a button to pause the game and display a screen that could show health, number of hearts, and available time (although currently there is no in game timer).

 

Having a boss health bar is something I have considered, I also had thought about having the boss begin flashing (similar to Konami's arcade beat em ups) after the health is below a certain amount.

 

Right now my biggest issue is trying to fit everything I would like without exceeded the 42k limit. I had reached it a month ago, and since then reworked a large amount of the game to reduce the size.

 

 

Very cool!!

Some thoughts:

I think changing Simon's color to red when he's low on health would help let the player know how much health he has. And you can display the boss's health on screen using tiles since the screen isn't moving anymore.

I would suggest getting Jzintv emulator and a front end. Nostagia is less accurate than jzintv and my 42K mapped game won't boot in Nostagia. Jzintv does have built in video recording, you can press Win-A to record your gameplay to an AVI file. The downside, uploading to Youtube will drop the framerate to 30fps(because it's not 720p),loosing the multiplex'd frame.

The game is shaping up really well, keep up the wonderful work!

  • Like 1
Link to comment
Share on other sites

You can use the intellivision border colour as a status indicator. There are some tricks to have a few characters remain stationary during Intellivision scrolling e.g. Bump'n'jump. In some games they just let the indicators scroll. A pause button showing all the info is a good idea.

Edited by mr_me
Link to comment
Share on other sites

I like the smooth movement and excellent looking physics! Well done!

 

Hmm... I must have seen a different video because the one I saw had just two-frame animations and the jumping seemed more square than parabolic, halting at the zenith for a few frames.

 

I never played the original, so I do not know to what extent it mimics it, but I am not very fond of the bright colours and changing tile-patterns everywhere: they seem distracting from the action, and it's hard to tell what's what.

 

It does look like it has promise, but I would like to see it when it's more polished.

 

 

 

For the video I just tried to use the Nostalgia emulator. The framerate seems to be a little better on this old laptop, and you can easily map a controller. However for all my testing, I use JZIntv, it is a lot more convenient to load the game quickly. In fact I just use a batch file to compile, assemble, and run my intybasic programs on JZintv.

I may try using the video recording option next time, although I will have to see how much it affects the video, there is a bit of multiplexing and sprite colors changing on odd/even frames.

 

Right now I am using all the memory locations mentioned in the 42k sample file, although I am only using just over 36k. I still need to create bitmaps and level data for the last stage, as well as more routines for enemies / bosses.

I have wondered about altering Simon's color based on his health, or maybe have his outline flash a color. Whenever he takes damage, his health is displayed on the screen briefly. Another idea was maybe a button to pause the game and display a screen that could show health, number of hearts, and available time (although currently there is no in game timer).

 

Having a boss health bar is something I have considered, I also had thought about having the boss begin flashing (similar to Konami's arcade beat em ups) after the health is below a certain amount.

 

Right now my biggest issue is trying to fit everything I would like without exceeded the 42k limit. I had reached it a month ago, and since then reworked a large amount of the game to reduce the size.

 

 

 

Is the space consumed purely by the level data? Maybe if you post a sample of your data structures and storage scheme we may be able to offer alternatives. 42K is indeed a lot of space, but most definitely not unlimited. In a pinch, you could also try your hand at bank-switching, layering the level data on a single segment. That way only the data for a single level need be made visible at a time.

 

-dZ.

Link to comment
Share on other sites

Originally I had just stored the data as it was created with Intycolor. however, I opted to save space by creating 1x6 segments of grams, and then the maps would reference those 1x6 strips (one for the top half, and one for the bottom half, and as wide as the level) Fortunately many levels will reuse the same 1x6 sections, which ended up saving quite a bit of rom space. There is little overhead in the software, and I ended up changing all collision routines to reference backtab as opposed to the raw level data as I had originally done. There was some trade off since now enemies can't roam off of the screen as they used to, however, that is not a big issue since I need to continually swap out enemies to stay within sprite limits.

 

It seems with the original NES game, 16x16 tiles are constructed of 4 8x8 characters, and then 4 16x16 tiles are grouped in 2x2 clusters and referenced throughout the levels. I was considering trying to replicate that these 2x2 tile clusters, but was weary that there would be too much overhead when dealing with scrolling.

 

 

Hmm... I must have seen a different video because the one I saw had just two-frame animations and the jumping seemed more square than parabolic, halting at the zenith for a few frames.

 

I never played the original, so I do not know to what extent it mimics it, but I am not very fond of the bright colours and changing tile-patterns everywhere: they seem distracting from the action, and it's hard to tell what's what.

 

It does look like it has promise, but I would like to see it when it's more polished.

 

 

 

 

Is the space consumed purely by the level data? Maybe if you post a sample of your data structures and storage scheme we may be able to offer alternatives. 42K is indeed a lot of space, but most definitely not unlimited. In a pinch, you could also try your hand at bank-switching, layering the level data on a single segment. That way only the data for a single level need be made visible at a time.

 

-dZ.

Link to comment
Share on other sites

When I think of classic Intellivision games, I always remember games like Mission X where the score would scroll past the screen, or Super Cobra. I was even thinking back to AD&D Cloudy Mountain, where the number of arrows are represented by audible clicks. They really thought of interesting compromises when dealing with the hardware. Somehow I overlooked Bump N Jump. Looking at that, it seems as if they are using at least 7 sprites for the cars, and road hazard indicator, but can't understand how they managed to position 3 digits in a stationary position with everything else going on.

 

The border color is something I had not thought of, but will definitely look into that too.

You can use the intellivision border colour as a status indicator. There are some tricks to have a few characters remain stationary during Intellivision scrolling e.g. Bump'n'jump. In some games they just let the indicators scroll. A pause button showing all the info is a good idea.

Link to comment
Share on other sites

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.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...