Virtual Viewport
Displaying 1-16 of 16 total.
1
Please enter a numerical value for the importance of this sticky.
Enter 0 to unsticky.
locke

Here's a new one. Assume I'm building a car-racing game, top-down, and the car is a rotatable sprite. I have built a track, but it's much larger than the screen. I want to be able to track the car's progress as it moves around the track, with the car stuck in the middle of the screen.

Basically, I want to do what we can already do with maps, but I don't want to use a map. It needs to be free-form.

So I end up with two coordinate systems, one for the track and one for the screen. (let's say the track in this case is 3200x2400 to keep it simple, and I'm running at 320x240)

Let's assume I use 'track coordinates' to place objects, like circles and squares to represent some obstacles. So I might put a circle at x1200 y200.

How do I create a 'camera system' to update the screen correctly? I thought about simply dividing by 10, but that effectively just shrinks the universe down to fit on one screen. Do I subtract the x's and the y's, then draw based on that? But how do I tell it how to draw that circle on the screen when it gets close enough to be on-screen?

Thanks.

It's funny... I got it to work using one system, and it works ok, but basically I'm just moving objects around relative to the vectors of the player. I'd like to be able to move the 'viewport' around relative to the track.

Can I draw the entire track (with unviewable portions 'offscreen' and then just move the 'camera' around? In this case, how do I relate the two coordinate systems to eachother?

-l

Posted on 2004-10-05 18:02:59

mcgrue

If you're always drawing correctly to the master 'map' image that's 3200x2400, all you need to do to get the correct screenshot is:


int my_screen;

while( i_am_rendering_from_my_map ) {

my_screen = ImageShell( xofs, yofs, 320, 240, master_image);

Blit( 0,0, my_screen, screen );

FreeImage( my_screen );
}


You can draw to the large map-image at any coordinates, because images don't care about being 'on screen' or not. Then you can make an imageshell of what you want the current screen to display, and blit that to the actual screen.

Whenever using imageshell, remember to free the handle. This will not destroy the master's bitmap data, it just recycles the imagehandle.

Posted on 2004-10-05 18:11:19

locke

So...

For every render I am creating a new (screen-sized) with a snapshot of a piece of the larger image, blitting the new image to the screen, and then releasing the new image.

ImageShell is handy. It's exactly what I was looking for.

You guys thought of everything, didn't you?

btw: I sware I read the manual! I didn't see this.

-l

EDIT: WOOOT! Worked perfectly. Learned a quick lesson, though... you have to do some bounds checking. ;)

Thanks, McG.

Posted on 2004-10-05 19:00:31 (last edited on 2004-10-05 19:22:23)

Feyr

Drat. =P I just spent fifteen minutes writing an example, and the question is already answered with an easier method.

Well, maybe my answer still has its place. If you're using gigantic bitmaps for your track and don't want to hog system memory (a 3200 x 2400 x 32bit bitmap is close to 29.3 megabytes) then you can do what is done in this example instead.

In that example I created an array of obstacles (circles with semi-random placement around a 'track', which is an imaginary circle with a big radius) and a car (a rectangle that moves around the track at a certain rate).

The method of moving the car isn't important for this discussion, but what happens when it moves is. Every time it moves, the viewport coordinates are updated so that the car stays in the center of the screen. All coordinates are with respect to the map, and you translate between map and viewport coordinates like this:

car_screen_x = car_map_x - view_x;
car_screen_y = car_map_y - view_y;

and similarly for the obstacles. Once you have screen coordinates for each obstacle you can determine whether they would be visible if you drew them. If they're off the edge of the screen in any direction then you don't have to bother doing any drawing. Otherwise, you draw to the screen coordinates you found earlier.

If you run the example you'll see a counter in the top left that shows how many obstacles are currently in the screen.

Posted on 2004-10-05 19:17:51

locke

This is actually much closer to what I am doing.

I'm not using an actual bitmap, I'm building my tracks from pieces, so-to-speak. Like you said, an array of objects which I parse, draw, then take a snapshot, then draw relevent data to screen.

Now I'm trying to figure out how to handle it when a player approaches the 'edge' of the track 'map'...

Right now (within the last 2 minutes) I have it setup to set the vector length to 0 if x and y are within 10 pixels of a wall. I would then add an accident/crash animation, etc. But I'm wondering if there aren't better ways to handle this.

I need to do some bounds checking when the screen image hits an edge.

Man... this would have been much easier if I had used the Map functions. ;)

Now, if it was a free-form driving sim, I could make it 'warp' into a new area. Example: the 'track' now becomes a 'city', and moving from neighborhood (2000x2000) to a new neighborhood could be done with some basic border or hotspot checking.

Wow. This opens up a whole new world of tangents.

I'll never finish a game at this rate.

-l

Posted on 2004-10-05 19:30:44

Feyr

I'll never finish a game at this rate.
*snicker* I know what you mean. I've been working on a code generator that will write all the tedious bits of creating structures using DMA. Last night I had it finished, and then I thought, 'Hey, if I make -this- change then I can make subclasses of structures and the subclasses can use the functions intended for the base structure type!' So I did that and I was about to wrap it up when I thought, 'Well, if I'm going to be inheriting fields then I might as well add inheritable chunks of code.' After I finished that then I thought of this nifty idea for implementing polymorphism, so you could do like:

int joe, raistlin, magus;
joe = NormalGuyNew();
raistlin = MageNew();
magus = ArchMageNew();

CastFireball(joe, target);
CastFireball(raistlin, target);
CastFireball(magus, target);
// where CastFireball is a function defined in NormalGuy and possibly overridden in NormalGuy's subclasses, Mage and ArchMage

and have three different results from the fireball based on which subclass the object was created from, with all the code except the functionality specific to each subclass generated automatically. -_- Hopefully this is the last bit I'm going feel compelled to add, since I'd like to get to work on the game part of my game sometime soon.

Posted on 2004-10-05 19:41:31 (last edited on 2004-10-05 19:44:45)

Zip

You know Grue, when you said if someone was crazy enough they could impliment OO through DMA...
Also, if you're having bounds issues locke, an easy fix is use GrabRegion()
rather than ImageShell(), as you don't need to do anything apart from a straight blit anyway, there's no reason not to, and will save you a bit of code as it just gives transparent pixels on out of bounds.

Zip

Posted on 2004-10-05 20:13:38

mcgrue

Quote:Originally posted by Feyr

Well, maybe my answer still has its place. If you're using gigantic bitmaps for your track and don't want to hog system memory (a 3200 x 2400 x 32bit bitmap is close to 29.3 megabytes)


RAM is meant to be used! :D

Posted on 2004-10-06 06:00:53

mcgrue

Quote:Originally posted by Zip

You know Grue, when you said if someone was crazy enough they could impliment OO through DMA...


Actually, Zip, I did a crazy method of semi-OO like this in v2, based on some classes that aen made back on the day. I'd already started implementing the SotS Character Structure in v2 as a quasi-object DMA dealie about this time last year, when v3 was announced and I turned my eye to other activities.

You can even pretend there's types if you close your eyes real tight and do:


#define CHARACTER int


...and the such.

However, v3's structures alleiviated most of my desires for dma objects... instead of passing around an integer pointer to an allocated chunk of memory, instead we pass around indexes to global master-arrays of structures in v3. Different methodolgy, and mostly the same effect. The only thing I lament is the lack of dynamic allocation, but really, put a hard limit that your system will never reach by design, and 'taint no thang, dawg.

However, if Feyd's making an easy-bake oven for dma-structure creation, well heck, maybe I'll go that route myself. Perl's a bit messy for my liking, though... maybe we can wrap that up in a php/javascript object-creation form and have the source-creator all happy-sappy for public use here on the website. After all, not everyone has activeperl installed on their windows box, nor does everyone have shell access on a linux box.

Posted on 2004-10-06 06:09:03

mcgrue

Quote:Originally posted by Feyr


CastFireball(joe, target);
CastFireball(raistlin, target);
CastFireball(magus, target);


This is indeed an awesome idea. I don't know if you've given targetting much thought in the long-range scheme of things though. Generally, I like to have a pair of global values:



//the index of the user of this skill
int skill_user;

//the indexes of any and all targets
int targets[MAX_TARGETS];

//the number of valid targets in the above array for this effect
int target_count;


These two variables get filled up by any effect's targetting period, be it targetting a single ally/enemy, multiples of either or both groups, or the skill user himself. Then the specific effect-resolution function assumes that these two variables were set correctly and applies it's effects accordingly.

Were you making your target the first node in a linked list of targets to simulate this, or were you planning for just single targets per effect?

Actually, I have a whole passel of questions about your planned system, but I'll refrain from asking them all in one successive string. ;)

Posted on 2004-10-06 06:21:48 (last edited on 2004-10-06 06:22:11)

Feyr

Ahh, that was just a quick example of the sort of thing that would be possible. I'm going to be working on a little sidescroller first when I get the infrastructure done, and once I've gotten an actual game under my belt I'll see about moving onto something really hard like an RPG. The main reason for doing this (aside from the coolness factor) is that polymorphism will be very useful for the windowing system I'm about to write, and it will save on a lot of tedious and error-prone DMA handling that I would've had to do by hand.

By the way, I've pretty much finished the code generator that allows me to do all that. I've written four examples of increasing complexity using it, and I haven't seen any new problems with it for a while. I'm working on the fifth (and probably final) example now, a simple DMA-based string library that I'll use to illustrate how to encapsulate a DMA structure into another one without causing memory leaks as long as you remember to free the enclosing class, and then I'll toss the Perl script that does the generating to anyone who wants it, along with the examples.

I've done a fair job of bringing OOP to Verge (which may or may not be a good thing ;P), if I do say so myself...certainly better than I expected. The constructors will automatically fill in fields if you specify the field names as parameters, and will also allow you to pass non-field parameters for processing by any custom constructor code you include. The destructor statements for cleaning up after a class are passed along to its subclasses automatically, and they can add on to them to do their own cleanup. Get/Set functions for each field are generated automatically (though you can specify read-only, write-only and private fields if you want). Function inheritance and polymorphism work beautifully. You can specify an expression that will be used to come up with an extra amount of memory to tack onto the end of the class, if you need it (for something like DMA strings or variable-sized list nodes.) Field names are expanded in your code, so that something like

Code:
void PlayerGetAttacked(int Player, int CurrentEnemy) {
$HP$ -= $Monster.CurrentEnemy.AttackPower$;
}
EndCode

will expand to

void PlayerGetAttacked(int Player, int CurrentEnemy) {
dma.quad[ThisPlayer + CLASS_Player_FIELD_HP] -= dma.word[CurrentEnemy + CLASS_Monster_FIELD_AttackPower];
}

with all of the #defines generated automatically.

Comments indicating the different fields for each class, their access levels and whether they were defined in the current class or inherited from a superclass are generated automatically. Ditto for the inherited functions - comments indicate the function signature, whether they were first defined in the current class, inherited from a superclass, or overridden in the current class.

*cough* Okay, I'll stop gushing now. I'm quite pleased with the way it came out, and if anyone wants to see it then I expect to submit it after I get out of class tomorrow afternoon.

A quick excerpt from the polymorphism example before I head off to sleep:

Log('Everybody flex! (polymorphic style!)');
Log('Don't hurt yourself, Mage.');
Flex(mage);

Log('Show us that bod, Fighter!');
Flex(fighter);

Log('What's under the Ninja's shirt?');
Flex(ninja);

Log('Just give us a little peek, UberNinja.');
Flex(uberninja);

gives us this v3.log file:

Everybody flex! (polymorphic style!)
Don't hurt yourself, Mage.
He tries to flex, but pulls a muscle.

Show us that bod, Fighter!
He flexes his rippling muscles.

What's under the Ninja's shirt?
This guy is too cool to flex.

Just give us a little peek, UberNinja.
This guy is too cool to flex.


in which Mage inherits his Flex() from the Living base class, Fighter overrides Living's Flex(), Ninja overrides Fighter's Flex() and UberNinja inherits Ninja's Flex().

P.S. You might get your red/black tree in a few days if I don't find any major problems in my generator tomorrow. ;P One of the examples is a simple binary tree with insertion, sorting and in-order traversal with a callback function, like the ForEach() I did for the linked list...wouldn't be a whole lot more work to subclass it and override the insert function to do the red/black balancing.

Posted on 2004-10-06 07:11:37

Feyr

However, if Feyd's making an easy-bake oven for dma-structure creation, well heck, maybe I'll go that route myself. Perl's a bit messy for my liking, though...

Well, I ended up writing my own little mini-language for specifying the structs. Now that I have all the data structures in place it shouldn't be terribly hard to change the input format. Here's the simplest example I've written:


Header:
Feyr (kevinhobbs@gmail.com)
Generated from $FILE$
at $DATE$

Example of a simple DMA-based structure.
EndHeader

# Create a new class named 'Point'
Class:Point
# Set up some fields
Field:X:4:A 4-byte field named 'X'; the x coordinate of the point
Field:Y:4:A 4-byte field named 'Y'; the y coordinate of the point
# This is the constructor.
# int [field name] means to set a parameter in the constructor
# with the same name as one of the fields, and then
# fill in the field with the value that is passed.
Init:int X
Init:int Y
# This code is just going to be stuck into the constructor
# after the memory allocation is done.
Init:Log('** PointNew: Created a new point at '+str($X$)+', '+str($Y$));

# Here's our destructor. If you're using really complex
# objects you might need to do some memory deallocation here
Dest:Log('** PointFree: Destroyed a point at '+str($X$)+', '+str($Y$));


So there's no Perl code to mess with...I even wrote a .bat file to regenerate all the code from their definition files every time I start the Verge engine up, to make sure I don't forget and use stale stuff.

Packaging it up for the website would be a pretty cool thing...but it's heavily dependent upon regular expressions. I know Javascript's regexes leave a lot to be desired...is PHP any better? Hmmm...actually, I think I have Perl2Exe hanging around here somewhere. That would eliminate the need for ActivePerl.

Comments?

Posted on 2004-10-06 07:22:59

mcgrue

PHP has, I believe, perl-style regexp.

The javascript would be to manipulate the html forms, for adding new rows of inputs for new data members, etc.

My whole point is that if it has a happy-shiny GUI face on it, more people will use it, even if it's only meant to be used by people who can handle CLIs.

People generally are more likely to use something that panders to them. I know I'd either like a web-interface around such a util, or a quick'n'dirty VB app... and I offered a web-interface because I'd be much quicker at it than at making a windows app.

Posted on 2004-10-06 07:32:53

Feyr

Oh, that whole user-friendly thing. *cough* Right.

If you want to do it, I certainly don't have any objections. I probably wouldn't be much help without a week or so learning PHP, but you're welcome to work on it yourself. The code itself is a terror to look at, though...it went through three or four major revisions while I was in the process of writing it, and it's definitely not going to be easy to read. If you're just planning on making a front-end for it then that should be no problem...if you want to reimpliment it in PHP then you might want to wait until I can rewrite it more cleanly.

Here's the code and the four completed examples along with a system.vc to run them.

The script takes either a single filename from the command line, or it will ask for one interactively if none is given.

Posted on 2004-10-06 07:49:05

mcgrue

Actually, I could probably get away with cheating, really.

Just use the webpage to build the makfile format, then send it to the script on the system, then fetch back the output.

I'll have to ponder your arcane format when I have more sleep in me, however ;)

Posted on 2004-10-06 08:25:47

locke

Also, if you're having bounds issues locke, an easy fix is use GrabRegion()
rather than ImageShell(), as you don't need to do anything apart from a straight blit anyway, there's no reason not to, and will save you a bit of code as it just gives transparent pixels on out of bounds.


This is another beautiful thing.

You guys make me so proud.

It works like a champ.

-locke

Posted on 2004-10-06 13:20:53


Displaying 1-16 of 16 total.
1
 
Newest messages

Ben McGraw's lovingly crafted this website from scratch for years.
It's a lot prettier this go around because of Jon Wofford.
Verge-rpg.com is a member of the lunarnet irc network, and would like to take this opportunity to remind you that regardless how babies taste, it is wrong to eat them.