CP - Alien Breed Remake - 8

Miscellaneous Forums/Blitz Showcase/CP - Alien Breed Remake - 8




Download site

On-Line Todo list

Previous Threads:
Initial Idea thread: http://www.blitzbasic.com/Community/posts.php?topic=37615
Thread 1: http://www.blitzbasic.com/Community/posts.php?topic=37773
Thread 2: http://www.blitzbasic.com/Community/posts.php?topic=38098
Thread 3: http://www.blitzbasic.com/Community/posts.php?topic=38223
Thread 4: http://www.blitzbasic.com/Community/posts.php?topic=38400
Thread 5: http://www.blitzbasic.com/Community/posts.php?topic=38864
Thread 6: http://www.blitzbasic.com/Community/posts.php?topic=39203
Thread 7: http://www.blitzbasic.com/Community/posts.php?topic=39435

Zips Updated:

SFX, GFX and Code all need to be re-downloaded.

I've done a bit of housekeeping to clear out old unused stuff, check out the history for all the details.

I've still got to do a lot of work in Aliens.bb so if anyone is touching that let me know.

Bugs:
- I've extended the map to the full width of the available area and collision doesn't work right over on the right hand side... Not sure why.
- I successfully got myself trapped inside a wall, no idea how.
- I've noticed is that you sometimes appear to pick up 2 keys instead of 1. I've no idea how that can possibly happen but it does seem to happen.

I've created 2 new alien graphics, these aren't in this upload as I've not done a class.txt file for them yet. One is a baby beast though.

The beast now shoots, and he's really nasty!

We need to come up with a difinitive todo list, no-one appears to be using the online one... please do!

We now all the way to thread number 8... well done guys, we're nearly there!

Didn't get as much time over the weekend as I hoped to get on top of the object editor. And don't have that much time over the next few days. This week, I shall be mostly hacking editor.bb again, although in a fairly self-contained fashion.

I'll have a go at sticking stuff in the todo list tonight - I'll go back over the past few threads and add stuff in. If I have time, I may check out that 2 keys for the price of 1 bug - sounds weird!

Rob, could you stick links to the old threads in the top post? I'm about to trawl them for TODO's, and it would be kinda handy for reference... ;-)

I've trawled through threads 5, 6, and 7 looking for TODO's. There are a fair few! I've just dumped them in a text list for now (see codebox below if you're looking for something to help out with!). They need to be prioritised yet (and describe better!), but it's a start. I won't get a chance to put this in the proper todo until tomorrow at least.

animated tiles
sound emitting tiles
mini-game(s) for Intex
spawn animations - emerge, materialise
gun-specific gfx on player
more tiles (boxes, different walls, floors.  themed tilesets - underground, office, outside, forest?)
motion detector
rooms to be 5x5
player glow on intex map
game modules (skin menus, etc.)
gun recoil
diagonal corridors?
load / save game
Game structure - On starting the game (and loading), you see a world map (the image is defined per game module). Available locations appear on this map, and you can choose where to go. Different locations take you a start level, which then is a linear progression of any number of levels. Finding stuff in the levels can then unlock other levels on the map. This gives the benefits of non-linearity (choice of order to do things, ability to try something else if you get stuck), but without having to worry too much about it when building a 'location' which may consist of 5 levels which you make your way through in a largely linear fashion. Obviously player classes, etc will allow a limited amount of non-linearity within a location (i.e. different solutions to same problem), but essentially they remain linear. Never played tower assault (I know, I know!), so don't know if that's close?Also, this structure might have an impact on our save/load options - we could restrict saving / loading to only be on the world map, and partial progress in individual locations is NOT remembered, just completion of locations. On death in a level, we simply reset the entire level back to it's original state. It's a simple approach, but makes our save function dead easy...
level intros (slideshow, music, text)
editor to 'compile' levels into single file.  Or at the level of game modules?
level.lvl (to go with level.map and level.obj) that can contain all this stuff like which tileset to use (I suggest we do define it once per level), completion criteria, intro graphic (movie?), intro text, whatever.
HUD
level self-destruct (and words from Rob's gf)
health packs to be inventory items, not immediate use, but auto-use when health is low (optional?)
Laser Tripwire
Puzzles - For example with the laser trip wire, you could provide objects to let the player either 1) just run it and set the alarm and blast loads of aliens 2) find the passcode and control device to turn it off 3) find access to the aliens hiding place (a grille in the wall) and gas them, then just run the laser trip wire with the aliens dead. 4) set up a mine in advance of the trip wire, then throw something at the tripwire, aliens come out and get slaughtered...
Puzzles - switch combos to open doors
Scripting - if, setvar, checkvar
optional 360 degree rotational controls?
I have a suggestion for making aiming easier. I tried to aim in a certain direction, and then fire the gun (without walking). For left/right, up/down, this is not a problem, but it is very hard to do this for diagonal directions. For instance if you press up+right, in most cases one of the two buttons will be read separately when you release the keys.  I noticed this problem in one of my own games as well, and solved it by building in a small delay when selecting a new direction: if the player "activates" a different direction than the current one, the character won't immediately change into that direction. First he will have to keep selecting that direction (= keep the keys down) for a number of game loops. (If all keys are released during this count, the counter would be reset to zero.) This way if he is pressing up+right and tries to release them both at the same time, non-perfect timing is allowed for. Of course the time delay (the target count) should be very small so that movement (when you actually *want* to change the direction, as is most often the case) is not slowed down noticably.
re-closing doors
half-height flag for barrels etc
online score board / timings?
slowdown jitters & craziness
improve drawmap()
flamethrower
weapons with dual actions
dropping stuf from inventory
BUG: right hand side of map dodgy.  Note old thread5 comment by Pert "If the player walks to the far right of the map, they are prevented from going within about 6 squares of the edge."


Priority 1-5, 5 being high:

(5) Animated tiles / Sound Emiiting Tiles: Funnily enough I was thinking about this earlier, if we added a layer to the map that deals with level sounds and animated graphics, this way we can do a simple distance check and trigger the sounds or start to draw the graphics (if visible) and likewise stop the sounds and stop drawing the graphics, maybe even load and unload them, although I'm not sure how much slowdown that would incur. This layer could be something you could look into as you're the map guru now!

(1) Mini-Game for intex. We've really got to work out what the intex system is for, I'm disliking the idea of picking up money and buying weapons/keys/health etc. It seems wrong to me. Regarding a mini game this is LOW priority!

(3) Spawn animation could be simply done with a particle, this may mean an addition to the particle system that after a particle life is spent it triggers a script. This can be done very easily by adding a script to the createparticle function, if it has a script it triggers it on death of particle, if it doesn't have one, it acts as it already does.

(1) Gun-specific gfx on player: Quite frankly I think it's more effort that it's worth, again, low priority. It's candy nothing more.

(2) Motion Detector: Again, I'm not sure if it's worth it, we'll have to decide if it works as a radar or just if there is motion infront of you? Is it a visible thing or just audio? etc etc. Discuss.

(1) Rooms to be 5x5: Over to you Mark, I think this is another nice to have on the editor along with the 'shapes'

(1) Player Glow on intex map: It does! I think!

(1) Game Modules: Low priority, I think once we've got the map data sorted - Objectives etc then we can look into this.

(1) Gun Recoil: Um... Throwing the player back? The screen shaking gives you the impression of this really well if we need more than this let me know and I'll look into it.

(1) Diagonal Corridors: Right... I like the idea of this, however, it would mean some serious thought, probably new types of collision block for the various angles, doable, how important is this to everyone? It would be nice I agree. I've put this at a (1) if we want this we can ramp up the priority.

(1) Load / Save game: This is in to a certain extent, I thought we were just going to have load / save at beginnings / ends of levels. If this is the case then again, it's wait until we've actually got the map data complete before we can even start knowing what to save or load.

(1) Game Stucture: See Load/Save game.

(1) Level Intros: See load/save game.

(1) Level self-destruct: Again this is just triggers, and objectives. Should be able to achieve this with level design.

(3) Puzzles / Scripting: Triggers! Yeah yeah!

(1) Optional 360 rotation: Quite frankly I think we're a bit beyond implementing this now without a major reshuffle, if people think it's a definate yes then I'll look into it.

(4) Aiming: Yeah, should probably put this in.

(2) half-height flag for barrels: Already worked around this apart from the grenades going through closed doors!

(1) Online Scoreboard : Low priority, lets get the rest in first!

(5) slowdown jitters & craziness: Um...

(5) improve drawmap(): How?

(1) flamethrower: Done!

(5) weapons with dual actions: Doing it!

(2) dropping stuff from inventory: Again, we'll have to see how we use the inventory, personally I don't think we should have so many items that this would be necessary. After all, this is a shootem up rather than an RPG.


Just to update you on what I've been doing, I've implemented turn speed to the alien class file, this means that you can set how fast they turn around, ie, big aliens don't turn as quickly, this also cuts down the big aliens break dancing somewhat!

Oh, items that should be able to be picked up, the bombs! I don't think these should be a weapon as such, just items that can be picked up and used, this way you don't end up with 100s of bombs going off... although that does look cool!

I did warn you it was just a dump of ideas - most I agree are way down the priority list! A few comments:


(5) Animated tiles / Sound Emiiting Tiles: Funnily enough I was thinking about this earlier, if we added a layer to the map that deals with level sounds and animated graphics, this way we can do a simple distance check and trigger the sounds or start to draw the graphics (if visible) and likewise stop the sounds and stop drawing the graphics, maybe even load and unload them, although I'm not sure how much slowdown that would incur. This layer could be something you could look into as you're the map guru now!


Will do, after the objects and level objectives. I seem to keep saying that... ;-) Originally I thought this could be dealt with using scripts, for example an ondraw() trigger might have a script of playsoundcont(fan) or playsoundrand(5,scratch). Not quite so sure now, but will think about it.

(1) Mini-Game for intex. We've really got to work out what the intex system is for, I'm disliking the idea of picking up money and buying weapons/keys/health etc. It seems wrong to me. Regarding a mini game this is LOW priority!


Agree from our POV. But, it's something that anyone else out there who's paying any interest in the thread might want to contribute to. There are several things like this that *we* don't want to focus on, but would be easy for others to pick up and have a play with (just trying to encourage some more people to join the fray!)

(1) Player Glow on intex map: It does! I think!


Again, just did a dump - I thought it might already do this, but thought I'd double check once I'd got the lot!

(5) slowdown jitters & craziness: Um...
(5) improve drawmap(): How?


Whilst fiddling with drawmap I thought I could see a (non-trivial) means of speeding it up. Both of these are really a reminder for me. Tied to this, I also want to amend the level save to do some double checking that there aren't any redundant tiles that will never be shown (base tiles under block overlay tiles for example).

Will trawl threads 1-4 tonight for more. While we don't want (m)any more new suggestions, if anyone reading does have some comments to make, bugs to report, etc, now might be the time to speak up and get them logged & prioritised. Once we've done this exercise, that really should be it for feature requests...

Agree from our POV. But, it's something that anyone else out there who's paying any interest in the thread might want to contribute to. There are several things like this that *we* don't want to focus on, but would be easy for others to pick up and have a play with (just trying to encourage some more people to join the fray!)
I agree which is why I said "We've really got to work out what the intex system is for" it's an open discussion. However, this CP appears to have lost the interest of the community!

Originally I thought this could be dealt with using scripts, for example an ondraw() trigger might have a script of playsoundcont(fan) or playsoundrand(5,scratch). Not quite so sure now, but will think about it.
I think it'll be difficult to do this with a script the continuous sounds have to be constantly monitered to make sure the volume and pan is correct, also it would mean scanning the surrounding area including off screen for these scripts. Likewise with animated graphics, you'd scan for scripts and the draw whilst on screen not when off screen. I think it'll be damn tricky to do as scripts.

Actually thinking about it... Each sound and graphic would need a unique ID to keep track of it... maybe a script would be better... Need more thought!

I'm thinking that the playsoundcont and playsoundrand script triggers are scanned for over the visible map area "plus a bit". Any new ones not seen before are added to a "playlist" (a type), and any on the playlist that are no longer in the scanned area get removed (although it may be neatest to remove them after a short period of them not being visible to avoid funny clipping when walking diagonally, etc). Once that's done, you work through the playlist and determine whether it's a continuous sound; if it is and isn't playing, make it play. If it's not, decide whether to play it again, either after a fixed period or after a random period between N and M seconds.

I suspect that your sound engine can handle a fair bit of that, but I haven't thought beyond the above at all (and even then, the above is largely off the top of my head!), or delved in the appropriate bits of code to know whether I'm talking crap or sense!

However, this CP appears to have lost the interest of the community!

Hopefully once we have something like a real game structure in place we can garner some more interest and pimp it some more - more standalone activities can be taken on by people new to it, e.g. designing levels; designing puzzles / scenarios within levels; creating art / tiles; creating mini games; all those neat bits that we'd love to do but need to get the core sorted first!

I havent lost interest, I think its a sterling piece of team work and its a great game to play, keep it going.

Oi the rest of you, give our boys some support would ya ! :)

I have to admit, my recent silence in these threads is because I have no idea what I can contribute anymore, I'm a bit lost in the code (I'm by no means an expert programmer).

It's got to be said Pert the code is a disaster area!

But assistance doesn't have to come in the form of code, there's graphics, sounds, ideas, etc all of these have equal value as far as I'm concerned. I try to add the word Discuss to anything that needs discussing, however, it only seems a couple of people join in said discussions.

This to anyone watching, this is not just about coding this is about sharing thoughts and ideas and making this a better game. Even if you think your idea is stupid, or way out there, express it. Ideas are never wrong, ideas can be shaped by others to be a solution. Never be afraid to express them.... I'm ranting aren't I... sorry.

But you get my point... If you think we're doing something wrong then say it... without input we're nothing.

I just ran the latest code and found a couple of bugs:

1) the doors do not open if you move into them diagonally

2) whilst shooting at an alien and a face hugger (with my facing locked in position as diagonally left), I was no longer able to move left or up (it would play the animations but acted as though there was a collision zone there, this happened no matter how far down and right I moved to try and offset it.

1) I know! I'll look into it

2) If the aliens are infront of you they will stop you moving in that direction... was that it?

Also player / alien / grenade collisions when you're all up close look plain wrong. You get stuck, the alien gets stuck, the grenade goes vertically up and down (I know I mentioned this elsewhere already) - it just looks freaky! Don't know if it's related / the same problem?

As for the code - hopefully the editor tidy has helped clarify some areas of that, and makes it slightly easier to get your head around. However, I think we need to be a bit more conscientious about commenting - I know I'm not great at it - but if we don't then there's no chance of someone else understanding our code.

Right, I'm off to trawl threads 1-4 for any interesting TODO's...

Just back from my holiday Down Under. A lot has happened.. the game turns out great!

Sorry I haven't been contributing lately, been really busy with no real time to do anything.

At stated, the Intex system does not appear to have much use at this stage. I guess we can either take the road of keeping similar usage to AB (purchasing weapons, items, maps etc) or do something totally different and new?? Rob and Mark may have a better idea as to the direction of the game currently and what using may be gained from this area.

I'll check out the TODO list once I have some spare time...

Rob and Mark may have a better idea as to the direction of the game currently and what using may be gained from this area.

I like the way the map is only available at intex points, and I think we could expand on this. For example you could have a security item that always exists somewhere in the level, that if you have it, you can see all aliens & spawn points on the map. This would be useful if we add bonuses for completely clearing a given level.

Another thing that I'd quite like to see is a basic 'email' type thing, I guess similar to that in Deus Ex. This could be used for developing story, and very occassionally for puzzles (I'm not too keen on having to check every last intex machine without knowing you have to check them).

I also wondered about a simulated hacking tool / os. e.g. a simulated directory structure and you can root around in there to find stuff. Again, not too keen on this from a gameplay point of view for similar reasons - this is a shooter, not an RPG - but could be a bit of fun - a mini-game in itself perhaps? Or how you gain access to mini-games?

The intex systems should also provide access to online info if we ever get that far: game updates can be called intex operating system updates, new game modules could be "advertised" as trips to exotic planets?

However, all of those really are nice to have features, so let's log 'em and get on!

Anyway, apologies, but I didn't get a chance to do much in the end tonight. Must . Try . Harder . ;-)

The whole buying weapons and stuff from Intex systems I think is a little against what we're doing here. The game is now more realistic (if there's such a thing) as the original, moving in the direction of inventory etc. I like the idea of finding weapons stores and ammo rather than buying stuff as you need it.

Why would marines be sent in? To find money and spend it on more weapons... seems kinda silly to me. Maybe if they're bounty hunters instead, but again, they'd come armed to the teeth and not be assisted by intex terminals to that extent.

We need a list of ideas for intex terminals:
Intex terminals should have the radar service for sure.
Player stats
Level stats/objectives
Maybe have communications through the intex terminals to advance the plot? (email was suggested)
Yeah, hacking around it for the odd game of pong or something!?
I like the idea of adverts appearing on them, even if they do nothing, I think it would be in-keeping with the future... adverts everywhere!

But we need to concentrate on what this game is... it's a blast-a-thon... and this we need to keep in focus.

I'm working on a messenger service at the moment, this will be handy for ingame messages as well as debug info.


2) If the aliens are infront of you they will stop you moving in that direction... was that it?


I killed them, and I still couldn't move up or left, perhaps it is something in the code that handles that but I couldn't tell you for sure. (I doubt it's easy to replicate).

also, from a gameplay point of view, the weapons keys are not clear, it would probably be easier to move the controls onto the qwerty section of the keyboard, use wasd for movement and the number keys for the weapons (that way you can simply have the number for the weapon displayed in the corner of it's icon).

I think the mapfunction in the intexsystem would be nice, maybe even a radar function so you can plan (possibly) the best route in a level.

A self destruct mode with self ajustable timer.. to blast everything up just before you exit the level/ship.

Pert, Player 2 uses WASD, I think there should just be 2 weapons keys anyway, weapon up and weapon down. That said, keyboard will be definable anyway so it's not really worth worrying about.

Snader, The intex systems do already have a radar service.

keyboard will be definable anyway

Speaking of which, *that* is a needed TODO that should be self-contained enough for someone else to pick up?

As for intex systems, I did consider suggesting that objectives go in there, but I didn't think that made much sense. Objectives are something that you should be able to call up as a reminder at any time - they represent your long term memory. I'm also a little wary of having anything too player specific in the intex systems. If you are invading a base that's not yours, would you really be able to access your home email and personal stats?

As for credits and shop, maybe that should exist outside of the levels? If the game is to be presented as a world map with locations to visit (each location representing a start level), then you could conceivably put the shop function here. i.e. you get back to base and can then top up on ammo, kit, whatever before heading to the next location?

The question is are the intex system base specific or is intex like an internet terminal where you can log on to your email, get news, download porn etc.

Yep Redefine keyboard should be on todo as well as gun up/down rather than individual keys for each gun.

Just a thought for the objectives maybe have an inventory item that you always have that is your pocket computer or something? Click on that in the inventory and you're away with any additional info we care to throw at the game? Of course having a pocket PC with you kinda does away with the intex terminals.

Looking really great, I bet the code is becoming fun :)

If you need assistance with specific music / sound fx / graphics I'd be happy to have a crack.

I've just finished off the messenger service for displaying stuff on screen, looks very nice, sine smoothness as it rolls on and off... I'll probably do an update this evening... depends what's on tele really!

I kind of like the PocketPC idea, this could record player stats too. You could also use this as a special device with other objects. For example to hack into a (non-intex) PC to download data?

I think intex should be, in effect, the intranet for a given location, providing access to internal email, radar, maps, etc. i.e. level specific stuff. The PocketPC is then your personal portal to the outside world, and stuff gets downloaded to it from intex (e.g. mini-games, email messages, files).

Telly tonight - Titchmarsh being annoying I think.

some way to override the gun turrets would be a good thing.

ooh, neat! And cameras. Or is that just pinching from Deus Ex?

how exactly would cameras be implemented?

When you're at an intex console, you can select a camera. This then lets you view a certain location.

In terms of how it would work, I suggest the camera points to a single tile on the map. If that tile is not already visible (i.e. you've not been there), vis it. Then show on screen that map location as per the game map draw routines. Just don't draw the player or HUD, and any key exits. So you'll see the room, anything in it, plus anything you know about the surrounding area. And, once you've viewed the area, that stays visible for you, helping you out when attacking a horde of aliens.

Updatette:

Delta changes (650k)

Basically added turn speed to the alien class, updated the tile set a bit and therefore the map too. Also added the messenger system that I think is very cool, but hey, I would! Anyway, this shows up the picking up 2 things instead of one as I've messaged every time you pick something up. It's a bit weird the picking up 2 things instead of one bug...

Just so you know, I've now trawled all the threads and have a list of ideas. How do you think we should hold this? Do we like the online todo list, or not? I'm not convinced the 3 priority levels it provides is enough (I like 4 : DO IT NOW!, Needed to make this a game, Want to have, Nice to have). Back to a simple text list? Anyone have a preference? I'll post them wherever tomorrow, although they're still largely a braindump and need some tidying up / explaining!

I think a text list is by far the simplist way of dealing with it quite frankly!

Yeah, I was coming to the same conclusion! I'll try to post a tarted up version tonight - I may copy the format used in the project plasma thread.

.

todolist in progress!

Not going to be able to spend a a lot of time on this over the next couple of days as my mum is visiting! I'll keep an eye on it though!

Items with a * against them have further details in the engine documentation *here*.

ENGINE
2 keys for the price of 1
Doors do not open if you move into them diagonally
Killing an alien when up against them can be screwy?
Grenade anim needs to drop to the ground quickly if it hits something
Slowdown jitters & craziness
Animated tiles
Sound emitting tiles*
Improved Aiming*
gun selection to be up / down list, not specific to each
weapons with dual actions
Spawn animations*
Tile graphics*
Tile decals*
Game load / save game*
Destructible / Fixed number respawn points*
End Game tidy up*
Flamethrower - done?
configurable keys, etc (Space_guy offered some code in thread 1)
Motion detector - maybe in intex? Only accessed with a key / security code for the level?
Level self-destruct (and sfx from Rob's gf)
Improved HUD
Laser Tripwire
Health packs as inventory items*
PocketPC*
Intex - turret override*
Intex - cameras*
Animated opening / closing of doors
Elevators
Set piece on game start for 1UP / 2UP*
Gun recoil
Diagonal corridors
Mini-game(s) for Intex / PocketPC
Gun-specific graphic on player
Optional 360 degree rotational controls
Online score board / level timings? Update notifications?
Inventory - Drop*
Intex - email system*
Intex - adverts?
Joystick control
Device independent renderer (2D/3D)
NPC alien types? Conversations?
Moveable objects*
slopes and sticky areas that player falls, gets stuck in etc. (no instant death though!)
Alien acid blood*
Antony's map code from threads 0 & 1 never went anywhere...
player glow on intex map

EDITOR (& ENGINE)
Level definition file*
Level objectives*
Object / script editor*
Game structure*
Convert Rooms to Shapes* (see Rob's copy & Paste)
Half-height Flag*
Game modules (skin menus, etc.)
Level Compiler*
Tile Editor*

GAME IDEAS
Puzzles*
Levels to fit Mark's(?) story (thread 4/5?)
Fancy level intros (slideshow, music, text, movie?)
Faithful remake*

SCRIPTING
destroy(nearby|<Radius>)
opendoor(x,y) - switches to open doors
onplace() trigger*
givefullmap() - full level map as a pickup object.
re-closing doors (using switches)
setvar(varname,value)
checkvar(varname,value)
if(varname,value,truescript,falsscript)
showdocument(text)
showconv(text)
remove(nearby)

OTHER
Screenies in gallery
License statement (GNU GPL?)

ALREADY DONE? (haven't double checked!)
respawners to be count limited (total and on-screen)
Push scroll... Instead of the player being fixed in the middle of the screen the player walks around in the centre section of the screen and when he reaches a boundry will push the scrolling.
"createalien(x,y,hugger)" - creates a hugger at the objects x,y location
"createalien(px,py,hugger)" - creates a hugger at the players location (may be different to object)
"createalien(x-1,y+1)" - creates a hugger SW of the object (useful for creating a generic trap that creates 4 aliens around the trap)
"createalien(123,456,hugger) - creates a hugger at a very specific location on the map (useful for very specific scripted events)

Just a bit to do then! Note that the order within the four categories is not intentional, just the way they fell!

Please shout up if there's anything missing, or you think is rated incorrectly. Basically Red stuff we should do be focusing on, yellow stuff we need to do before we can truly call it a game. Blue stuff we likely won't do, but they're cool ideas to keep. Green stuff would be neat...

Mark, can you change the create alien hugger bit to have "hugger" as a string? This would make life much easier for the spawn alien as it then just looks in the "hugger" folder. As it stands it picks up the hugger constant (0 I think) then in the create alien bit converts the 0 to "hugger", seems a bit pointless! Also it means in the future more aliens can be added and it'll just work with no additional code.

I've just drawn a space ship!



I've been thinking about saving "shapes"

How about you just drag an area on the map (like when you create a room) and it saves that as a shape (all the layers) this way you can create prefabs in the editor as per usual, when you add a shape it just adds all of the layers on but doesn't affect anything that isn't set.

For example, with the space ships you could draw it on a 'nothing' background drag a window around it, save it as ship.shape then when you want to add ship it adds it to whereever the cursor is.

Make sense? Should be pretty easy too.

Updated the editor to do what I was saying... very hacked in, but it works! Mark, you might want to tidy this up and put it in functions and includes and stuff!

[edit]Updated zips[/edit]

Just so you know, I've added in a couple of variables at the top and a bit after everything is drawn.

Hit tab to start the copy and tab again to stop the copy, hit Q to paste what you've copied, no save yet.

If you want to find the bits I've added search the code for the following:

; pick up variables (could be better!)

and

;******************** Pick up temp bit needs gui-ing up!

It's only a couple of lines of code, but it certainly makes life easier!

And just finished a buggy:



Zips updated

07-11-04 :
Rob:
- Adjusted map and script so the door open sound open on script rather than door, this way you only get the sound once rather than many layered.
- Updated editor to allow for basic copy / paste functions (use Tab to start/end copy and Q to paste)
- Added Scenary GFX and updated map
- Updated spawn alien to spawn by name rather than number


Cool ship / buggy! Like the idea for shapes, haven't had a chance to do much, not even download the above (daughter has a chest infection, so have been in and out of doctor's etc the past couple of days. nothing serious though, just difficult!). Hope to get onto some of this later, although the wife is insistent on dragging me to fireworks (yawn).

Okay, simple updates tonight, so I'm posting delta changes here. If you don't want to pull them in now, I can do this later in the week when I get to finalise some of the other editor stuff. However, these are useful tweaks, and fairly standalone, so should be easy enough to copy and paste!

I've made my improvement to drawmap() - by pre-determining the min / max tiles, I've removed almost 8,000 expression evaluations per draw-cycle.

Whilst doing this, I think I've also spotted and fixed the "bottom right of the map is screwy" problem.

In map.bb, replace gettile and puttile with the following:
Function gettile(x,y,layer)
	; sort out the block location based on pixel co-ord
	x = Floor(x/32)
	y = Floor(y/32)
	; the following four lines should be unnecessary!
	If x < 0 Then Return
	If y < 0 Then Return
	If x > 255 Then Return
	If y > 255 Then Return
	Return map(x,y,layer)
End Function

Function puttile(x,y,layer,newtile)
	x = Floor(x/32)
	y = Floor(y/32)
	; the following four lines should be unnecessary!
	If x < 0 Then Return
	If y < 0 Then Return
	If x > 255 Then Return
	If y > 255 Then Return	
	map(x,y,layer)=newtile
End Function

And also in map.bb, replace drawmp with this:
Function drawmap(xpos,ypos,layer,ineditor=False)
; This function draws the map
; NB: for all "if ___ then Draw ___" lines, multiply the expression by map(x+xoff,y+yoff,LAYER_VISIBLE)
; determine sizes
blocksize=32
min_x=-1
min_y=-1
If ineditor Then
	max_x=19
	max_y=14
Else
	max_x=20
	max_y=16
EndIf

; sort out the block location based on pixel co-ord
xoff = Floor(xpos/blocksize)
yoff = Floor(ypos/blocksize)

; find the pixel offset
xpxoff = (xoff * blocksize) - xpos
ypxoff = (yoff * blocksize) - ypos

; limit tile drawing are to map size
If xoff<=0 Then min_x=-xoff
If yoff<=0 Then min_y=-yoff
If xoff>255-max_x Then max_x=255-xoff
If yoff>255-max_y Then max_y=255-yoff

; draw base layer
; uses draw block so you don't need a cls and is quicker.
If layer = LayerBase
	For x = min_x To max_x
		For y = min_y To max_y
;			If x+xoff>=0 And y+yoff>=0 And x+xoff<=255 And y+yoff<=255
				If map(x+xoff,y+yoff,layer)>0 Then
					If map(x+xoff,y+yoff,LAYER_VISIBLE)>0 Or ineditor Then DrawBlock btiles,(x*blocksize)+xpxoff,(y*blocksize)+ypxoff,map(x+xoff,y+yoff,layer)-1
				EndIf
;			EndIf
		Next
	Next
EndIf

If layer = LayerObject
	For x = min_x To max_x
		For y = min_y To max_y 
;			If x+xoff>=0 And y+yoff>=0 And x+xoff<=255 And y+yoff<=255
				tile=map(x+xoff,y+yoff,layer)
				If tile>0 Then
					If ineditor Then 
						img=Abs(objectdef(tile)\image)
					Else 
						If map(x+xoff,y+yoff,LAYER_VISIBLE)>0 Then img=objectdef(tile)\image Else img=-1
					End If
					If img>=0 Then DrawImage objects,(x*blocksize)+xpxoff,(y*blocksize)+ypxoff,img
				EndIf
;			EndIf
		Next
	Next
EndIf

; draw other layers
If layer = LayerTop And use_overlay_layer
	For x = min_x To max_x
		For y = min_y To max_y
;			If x+xoff>=0 And y+yoff>=0 And x+xoff<=255 And y+yoff<=255			
				If map(x+xoff,y+yoff,layer)>0 Then 
					If map(x+xoff,y+yoff,LAYER_VISIBLE)>0 Or ineditor Then DrawImage dtiles,(x*blocksize)+xpxoff,(y*blocksize)+ypxoff,map(x+xoff,y+yoff,layer)-1		
				End If
;			EndIf
		Next
	Next
EndIf

; layer 4, block overlay no transparancy
If layer = LayerBlock
	For x = min_x To max_x
		For y = min_y To max_y
;			If x+xoff>=0 And y+yoff>=0 And x+xoff<=255 And y+yoff<=255			
				If map(x+xoff,y+yoff,layer)>0 Then 
					If map(x+xoff,y+yoff,LAYER_VISIBLE)>0 Or ineditor Then DrawBlock btiles,(x*blocksize)+xpxoff,(y*blocksize)+ypxoff,map(x+xoff,y+yoff,layer)-1			
				End If
;			EndIf
		Next
	Next
EndIf

; detail overlay
If layer = LayerDetail
	For x = min_x To max_x
		For y = min_y To max_y
;			If x+xoff>=0 And y+yoff>=0 And x+xoff<=255 And y+yoff<=255		
				If map(x+xoff,y+yoff,layer)>0
					If map(x+xoff,y+yoff,LAYER_VISIBLE)>0 Or ineditor Then DrawImage dtiles,(x*blocksize)+xpxoff,(y*blocksize)+ypxoff,map(x+xoff,y+yoff,layer)-1						
				EndIf
;			EndIf
		Next
	Next
EndIf


If layer = LayerHits And ineditor
	Color 255,255,255
	For x = min_x To max_x
		For y = min_y To max_y
;			If x+xoff>=0 And y+yoff>=0 And x+xoff<=255 And y+yoff<=255	
				If map(x+xoff,y+yoff,layer)=-1 Then Text (x*32)+8,(y*32)+8,map(x+xoff,y+yoff,layer),True
				If map(x+xoff,y+yoff,layer)>0 Then Text (x*32)+8,(y*32)+8,map(x+xoff,y+yoff,layer),True
;			End If
		Next
	Next
EndIf

If layer=LayerCollision And ineditor
	For x=min_x To max_x
		For y=min_y To max_y
;			If x+xoff>=0 And y+yoff>=0 And x+xoff<=255 And y+yoff<=255	
				Select map(x+xoff,y+yoff,LayerCollision ) 
				Case czStatic
					Color 255,0,0
					Rect (x*32)+7,(y*32)+7,18,18,False
				Case czDynamic
					Color 0,255,0
					Rect (x*32)+7,(y*32)+7,18,18,False
				Case czVisStatic
					Color 255,255,255
					Rect (x*32)+8,(y*32)+8,16,16,False
					Color 255,0,0
					Rect (x*32)+7,(y*32)+7,18,18,False			
				Case czVisDynamic
					Color 255,255,255
					Rect (x*32)+8,(y*32)+8,16,16,False	
					Color 0,255,0
					Rect (x*32)+7,(y*32)+7,18,18,False					
				Default
					;do nothing
				End Select
;			End If
		Next
	Next
End If

End Function

In players.bb, in Player_updateall, remove the bit of the if blocks relating to x/y being <7552. This is not only wrong (map tiles 236, not 255) but also unecessary.

Right, now I'm going to update the todo list and go to bed. Hopefully I'll get some sleep tonight!

Nice one Mark, I'll take a look at slipping this in tonight.

Code.zip updated with Marks changes... and a couple of fixes myself.

Nice changes!

Btw:
1. Will it be possible to play AB at higher resolutions as well or are you going to stick to 640*480?

2. For the editor.
a) I think up+down arrows for the tile selection should be on both sides
b) you could add: mousewheel for changing title view (arrow uo/down)

3. Why is the TODO List non-public?

Grisu,
1) We're sticking to 640x480, I did have a go at putting it in a higher res so you see more on screen, but quite frankly it didn't feel right, the graphics looked too small, and you didn't get a feeling of "what's round the next corner" so much.

2a) Personally I just use PGup/down to change the tile, I rarely bother with the gui.
2b) Not sure what you mean by the title view. However, the mousewheel 'did' change the palette, that's been broken somewhere along the line though.

3) The online to-do list isn't used anymore hence the big todo Mark post up there ^^^

Thanks for the infos Rob.

Mousewheel: After checking your code, the only thing u need to add is a "Global MouseOverTileset" to the var section and mousewheel works again.

Resolution: Well i tested 800,600 on my 17' monitor and nothing looked too small. Furthermore by the time the game comes out every pc should be able to handle at least that resolution!

It would be a really nice option to have! If you don't want to code that, I'll do it.... ;)

P.S.: How about using a free BMP fonts suite? Gives the extra speed for higher resoultions! ;))))))))))))

On 1), I think the time to think about this is if we ever wanted to fully separate the game and rendering engine. The original thought there was to enable 2D / 3D modes, but there's no reason why it shouldn't be capable of higher res - although it's likely to be tricky to achieve as Rob obviously found out. Another one of those for "When we're done!"

When we start the next thread, I'll try to post the todo list as the second post. Just give me some warning Rob when it happens!

Caff, if you're still reading, thanks for offering graphics help. I think we could do with more tiles, and transparent stuff to go over them. Big stuff like Rob's vehicles are cool. See the todolist above and the link to "docs" for inspiration.

Also further to what Mark has said about creating tiles. There is the splitter app that is being shipped with the code.zip now, this allows you to throw a graphic through it an it'll split it into 2 files, whole blocks or transparant blocks so these can be copy and pasted into the details and base tile sets.
I used this to put the space ship and buggy through so you can use block overlays instead of transparant overlays where necessary, this improves performance of the game so we're not doing a drawimage where a drawblock will work as well.

P.S.: How about using a free BMP fonts suite? Gives the extra speed for higher resoultions! ;))))))))))))
It already uses bitmap fonts.

Actually, what may be useful, is higher res in the editor. I found myself wishing that I could see more of the map at any one time yesterday.

So, Grisu, if you really fancy pulling apart the internals of the graphics, how about trying to up the editor only, but keeping the code shared? I'd prefer some help on the other todo's though...

As for the mousewheel thing, the best way to fix this (I hate globals for the sake of globals) is to amend the following two lines:
	;I know it looks like there is nothing in the quotes in the line below, but trust me, there is
	If (Button (0,490,32,"­",False,True,KEY_PAGE_UP,"Scroll up the tileset",False)=True Or (mz = 1 And mouseover)) And tileoffset > 0 And scrolldelay<0 Then tup=-1
	If (Button (768,490,32,"¯",False,True,KEY_PAGE_DOWN,"Scroll down the tileset",False)=True Or (mz = -1 And mouseover)) And scrolldelay<0 Then tup=1

Simply replace MouseOverTileset with mouseover (don't copy & paste, remember the dodgy characters!)

I have to agree with the editor thing, it's getting a bit crowded isn't it!

Editors are pain. I normally use a Blitz Gui for creating buttons and windows. So you dont need to code a file requester etc.

I can't promise to get sth done very fast as i have a full time job in real life. But if you are busy doing other stuff. I can try in the meantime.

Is there a map format list somewhere, so I know what infos must be stored where?

And the editor now uses the plain text commands. And it seems the main engine uses images. BUT these are no BMP fonts precisely spoken.

A nice idea might be to enlage the title placing area to 800x600 (as the engine should be :)). The editor win itself would be 1024x768 then....

Comments?

*coding*
Will post screen here later at night...

Phew done & Ready for Stress testing... :)

Changes:
% Editor: uses larger Palette & Tile Window (at 1024x768)
% Msgbar: black background


Editor.bb
; blitz3d version

; Last Modified by Grisu 11/09/04

; keys

; arrow keys move around map
; pgup/pgdown scroll through tiles
; return - pick up tile
; numpad4 - place a ground of 4 squares starting with the selected tile ie 12
;                                                                          34
; Space - Promote background tile to a over block tile

Include "inc\scancodes.bb"
Include "inc\soundcontrol.bb"
Include "inc\consts.bb"
Include "inc\gui.bb"
Include "inc\map.bb"
Include "inc\editor include.bb"
Include "inc\util.bb"
Include "inc\editor-room.bb"
Include "inc\editor-undo.bb"


; pick up variables (could be better!)
Global pick
Global pickx
Global picky
Global pickxs
Global pickys
Dim pickme(100,100,8)
; END OF - pick up variables (could be better!)



; set up graphics
Graphics 1024,768,32,0
SetBuffer BackBuffer()
loadGraphics() ; both version use this.
;had trouble when moving these to gui (symbFont did not exist for some reason)
Global font = LoadFont("Arial.ttf",15)
Global symbFont = LoadFont("Symbol.ttf",15)
InitGUI()

; check to load a level from the command line
If Len(CommandLine())
	load(CommandLine())	
Else
	createRandomMap()
EndIf

Global LastInput = MilliSecs()
Global sc_x=0
Global sc_y=0
Global scrolldelay = 0
Global mousescroll=False
Const setscrolldelay = 2
Global activelayer = 1
Global activetile = 0
Global tileoffset = 0
Global xpos
Global ypos
Global current_tool=1 ; 1=tile tool, 2=room tool
Global coll_tool=1

visible(LayerCollision)=0
visible(LayerHits)=0
refreshRoomList()
quickLoadRoom("maps\rooms\default.room")
statusMsg("Ready...")

main()
End

;---------------------------------------------

Function main()
	Repeat
	
		; very first thing we do is a clear screen!
		Cls
		
		; now work out where the mouse is : over the map or tileset / palette
		MouseOverMap	 = False
		MouseOverTileset = False
		If (MouseX()<860 And MouseY()<570) Then 
			MouseOverMap=True
		ElseIf (MouseY()>610 And MouseY()<768) And (MouseX()>32 And MouseX()<1024) Then
			MouseOverTileset = True 
		End If
	
		; deal with the common GUI elements (the RHS of the screen)
		handleGUICommon()		
		
		; next deal with the main editing area of the screen
		Select current_tool
			Case 3
				Color 255,255,255
				Text 50,50,"An integrated tile editor here would be neat..."
				
			Case 6
				Color 255,255,255
				Text 50,50,"Define objectives here, with ID numbers"			
				Text 50,65,"Need to define what constitutes completion for each"				
				Text 50,80,"Each objective can have a script assigned to run on completion, which might use new commands like:"				
				Text 50,95,"startlevel(basement), givelevel(nebraska), giveitem(medal),giveobjective(12,mandatory)"				
				Text 50,110,"Assign at least one objective as mandatory to each player"
				Text 50,125,"Additional optional objectives can also be assigned to each"	
				Text 50,140,"Note that not all objectives need to be assigned at the start"							
				Text 50,155,"some can be gained by completing other objectives, some by object scripts"				
				
			Case 7
				Color 255,255,255
				Text 50,50,"Define level settings here, such as:"			
				Text 50,65,"tilesets to use, object file to use"				
				Text 50,80,"info to show on level select screen (image, name, text, map location xy)"				
				Text 50,95,"background music to play"				
				Text 50,110,"movie / image / text to show on starting level"
				
			Default
				handleMap(MouseOverMap)	
		End Select
			
		; ******************************** TOOL SPECIFIC GUI
			
		If current_tool=1 Then ; TILE TOOL
		
			; map stuff
			If MouseOverMap Then
				; tile highlighter
				Color 0,255,0
				Rect (xpos-Floor(sc_x/32))*32,(ypos-Floor(sc_y/32))*32,32,32,False	
										
				Select activeLayer				
					Case LayerCollision,LayerHits
						handleMapCollision()	
					Case LayerBase,LayerDetail,LayerBlock,LayerObject,LayerTop
						handleMapTile()		
				End Select
			EndIf			
			
			; tile tool GUI
			handlePalette(activelayer,MouseOverTileset) 
			
		ElseIf current_tool=3 Then ; TILE EDITOR
					
			; TODO: Tile Editor!
					
		ElseIf current_tool=2 Then ; ROOM TOOL
			handleRoom()	
			handlePalette(LayerBase,MouseOverTileset) 				
				
		ElseIf current_tool=4 Then ; FILE MENU
			handleFileMenu()
			
		ElseIf current_tool=5 Then ; EXIT MENU
			If Button(880,745,140,"Confirm?",False,False,KEY_NONE,"Click to exit the editor") Then Exit
			
		ElseIf current_tool=6 Then ; Objectives editor
		
			; TODO: Level objectives editor
		
		ElseIf current_tool=7 Then ; Level Settings editor			

			; TODO: Level settings editor
			
		EndIf     
		
		;******************** SCREEN UPDATE
		drawStatusBar()
		DrawToolTip()
		
		;******************** Pick up temp bit needs gui-ing up!
		
		If KeyHit(15)
			If pick = 0
				pickx = xpos
				picky = ypos
				pick = 1
			Else
				pickxs = xpos - pickx
				pickys = ypos - picky
				
				For lllayer = 0 To 6
				For xxx=0 To pickxs
				For yyy=0 To pickys
					If visible(lllayer) Then pickme(xxx,yyy,lllayer) = map(xxx+pickx,yyy+picky,lllayer)
				Next
				Next
				Next
				pick = 0			
			EndIf
		EndIf
		
		
		If KeyHit(16)
			For lllayer = 0 To 6
			For xxx=0 To pickxs
			For yyy=0 To pickys
				If pickme(xxx,yyy,lllayer)>0 Then map(xpos+xxx,ypos+yyy,lllayer) = pickme(xxx,yyy,lllayer)
			Next
			Next
			Next 
		EndIf
		
		If pick = 1
			xx1=(pickx - Floor(sc_x/32)) *32
			yy1=(picky - Floor(sc_y/32)) *32
			xx2=(xpos - Floor(sc_x/32)) *32
			yy2=(ypos - Floor(sc_y/32)) *32
			Color MilliSecs() Mod 512 / 2,0,0
			Rect xx1,yy1,(xx2-xx1)+32,(yy2-yy1)+32,False
		EndIf
		
		;******************** END OF - Pick up temp bit needs gui-ing up!
			
		DrawImage cursor,MouseX()-1,MouseY()-1
		Flip
	
	Forever
End Function

Function handleGUICommon()
Local Startx=880
Local Starty=375, Starty1=640

	;*************************** core GUI elements
		
	; layers / visibility
	For n=0 To NumLayers
		If current_tool=1 And activelayer=n Then act=True Else act=False
		If Button(Startx,Starty+n*20,100,layername(n),act,False,n+2,"Edit this map layer") Then
			activelayer=n				
			If activeLayer = LayerObject Then tileoffset = 0
			If activelayer = LayerHits Then coll_tool=4
			If activelayer = LayerCollision Then coll_tool=1
			current_tool=1
		EndIf
		
		If Button(Startx+110,Starty+n*20,30,"Vis",visible(n),False,KEY_NONE,"Show / Hide this layer on the map")
			visible(n)=(visible(n)+1) Mod 2
			Repeat:Until MouseDown(1)=False
		EndIf
	Next		
		
	; other drawing tools
	If Button(Startx,Starty1,140,"Room Tool",current_tool=2,False,KEY_NONE,"Create and draw rooms") Then current_tool=2	
	If Button(Startx,Starty1+20,140,"Tile Editor",current_tool=3,False,KEY_NONE,"Edit tiles") Then current_tool=3	
	If Button(Startx,Starty1+40,140,"Objectives",current_tool=6,False,KEY_NONE,"Define level objectives") Then current_tool=6
	If Button(Startx,Starty1+60,140,"Level Settings",current_tool=7,False,KEY_NONE,"Define level settings") Then current_tool=7	

	If Button(Startx,Starty1+80,68,"File Menu",current_tool=4,False,KEY_NONE,"Load, save or create a new level") Then current_tool=4
	If Button(Startx+73,Starty1+80,68,"Exit",current_tool=5,False,KEY_NONE,"Exit the editor") Then current_tool=5		
	
	ry=GraphicsHeight()-140
	If First undoTile<>Null ;Undo tools
		If Button(Startx+73,Starty1-50,68,"Undo",False,False,KEY_NONE,"Undo all changes up to last reset")
			doUndo():Delay 200
		ElseIf Button(Startx,Starty1-50,68,"Reset",False,False,KEY_NONE,"Reset undo history")
			clearUndo():Delay 200
		EndIf	
	EndIf
End Function

Function handleMap(mouseover)
	;********************* MAP
	; draw the selected layers of the map
	For n=1 To NumLayers
		If visible(n)=1 Then drawmap(sc_x,sc_y,n,True);drawmap_inEditor(sc_x,sc_y,n)
	Next
	If visible(LayerCollision)=1 Then drawmap(sc_x,sc_y,LayerCollision,True) ; needs to be drawn last!
			
	; find mouse location on map
	If mouseover Then
		xpos = Floor(MouseX()/32)+Floor(sc_x/32)
		ypos = Floor(MouseY()/32)+Floor(sc_y/32)
		Button(2,560,28,xpos)
		Button(2,580,28,ypos)			
	Else
		xpos = -1
		ypos = -1
	EndIf

	;******************* INPUT HANDLING

	; map movement code (arrow keys and mouse near edge)
	key_left=False:key_right=False:key_up=False:key_down=False	
	If mouseover Then 
		If MouseX()<5 Then key_left=True
		If MouseX()>830 Then key_right=True
		If MouseY()<5 Then key_up=True
		If MouseY()>550 Then key_down=True		
		If key_left Or key_right Or key_up Or key_down Then
			If Not mousescroll Then mousescroll=True:scrolldelay=setscrolldelay
		Else
			mousescroll=False
		End If
	EndIf
	If KeyDown(KEY_ARROW_RIGHT) Then key_right=True
	If KeyDown(KEY_ARROW_LEFT) Then key_left=True
	If KeyDown(KEY_ARROW_UP) Then key_up=True
	If KeyDown(KEY_ARROW_DOWN) Then key_down=True
	
	; slow down the map scrolling a bit
	If scrolldelay < 0
		If key_right And sc_x<7552 Then sc_x=sc_x+32 : scrolldelay = setscrolldelay
		If key_left And sc_x>0 Then sc_x=sc_x-32 : scrolldelay = setscrolldelay
		If key_up And sc_y>0 Then sc_y=sc_y-32 : scrolldelay = setscrolldelay
		If key_down And sc_y<7552 Then sc_y=sc_y+32 : scrolldelay = setscrolldelay
	Else
		scrolldelay = scrolldelay - 1
	EndIf
End Function

Function handleMapCollision()

	If MouseDown(1) Then 
		Select coll_tool
			Case 1; static
				undoTile(xpos,ypos,map(xpos,ypos,LayerHits),map(xpos,ypos,LayerCollision))
				;if left control is held
				If KeyDown(KEY_CTRL_LEFT) Then	
					map(xpos,ypos,LayerCollision)=czVisStatic 
				Else 
					map(xpos,ypos,LayerCollision)=czStatic			
				EndIf
				map(xpos,ypos,LayerHits)=-1
				
			Case 2; dynamic
				undoTile(xpos,ypos,map(xpos,ypos,LayerHits),map(xpos,ypos,LayerCollision))
				;if left control is held
				If KeyDown(KEY_CTRL_LEFT) Then	
					map(xpos,ypos,LayerCollision)=czVisDynamic 
				Else 
					map(xpos,ypos,LayerCollision)=czDynamic			
				EndIf
				map(xpos,ypos,LayerHits)= lhDefaultHits ;see consts.bb for lhDefaultHits	
				
			Case 3; vis blocker
				undoTile(xpos,ypos,map(xpos,ypos,LayerHits),map(xpos,ypos,LayerCollision))				
				If map(xpos,ypos,LayerCollision)=czDynamic Then	
					map(xpos,ypos,LayerCollision)=czVisDynamic 
				ElseIf map(xpos,ypos,LayerCollision)=czStatic 
					map(xpos,ypos,LayerCollision)=czVisStatic			
				EndIf				
				
			Case 4; hitpoint tool
				undoTile(xpos,ypos,map(xpos,ypos,LayerHits),map(xpos,ypos,LayerCollision))	
				If map(xpos,ypos,LayerCollision)=czDynamic Or map(xpos,ypos,LayerCollision)=czVisDynamic Then
					;if left control is held
					If KeyDown(KEY_CTRL_LEFT) Then IncVal = 5 Else IncVal = 1 
					map(xpos,ypos,LayerHits) = map(xpos,ypos,LayerHits) + IncVal
					;limit the maximum value for a dynamic collisions hit points to 99
					If map(xpos,ypos,LayerHits) > lhMaxHits Then map(xpos,ypos,LayerHits) = 99
					Delay 100 ; not too quick now!	
				EndIf			
		End Select
			
	ElseIf MouseDown(2) Then 
		undoTile(xpos,ypos,map(xpos,ypos,LayerHits),map(xpos,ypos,LayerCollision))
		Select coll_tool
			Case 1,2
				map(xpos,ypos,LayerCollision)=0
				map(xpos,ypos,LayerHits) = 0
			Case 3
				If map(xpos,ypos,LayerCollision)=czVisDynamic Then	
					map(xpos,ypos,LayerCollision)=czDynamic 
				ElseIf map(xpos,ypos,LayerCollision)=czVisStatic 
					map(xpos,ypos,LayerCollision)=czStatic			
				EndIf
			Case 4; hitpoint tool
				undoTile(xpos,ypos,map(xpos,ypos,LayerHits),map(xpos,ypos,LayerCollision))	
				If map(xpos,ypos,LayerCollision)=czDynamic Or map(xpos,ypos,LayerCollision)=czVisDynamic Then
					;if left control is held
					If KeyDown(KEY_CTRL_LEFT) Then IncVal = -5 Else IncVal = -1 
					map(xpos,ypos,LayerHits) = map(xpos,ypos,LayerHits) + IncVal
					;limit the minimum value for a dynamic collisions hit points to 1
					If map(xpos,ypos,LayerHits) < 1 Then map(xpos,ypos,LayerHits) = 1
					Delay 100 ; not too quick now!
				EndIf						
		End Select				
	EndIf	
End Function

Function handleMapTile()
	; Left mouse button handler
	If MouseDown(1) Then
		If activelayer=LayerObject Then
			If activetile<numDefaultObjects					
				map(xpos,ypos,activelayer)=activetile+1
				If activetile = 37 ; give a barrel 5 hit points
					map(xpos,ypos,LayerHits) = 5
					map(xpos,ypos,LayerCollision)=czDynamic
				EndIf
			EndIf
		Else
			undoTile(xpos,ypos,map(xpos,ypos,activeLayer),map(xpos,ypos,LayerCollision))
			map(xpos,ypos,activelayer)=activetile+1					
		End If
	End If		
	
	;Right Mouse Button Layer Handler
	If MouseDown(2) Then
		Select ActiveLayer
		
			Case LayerBase
				undoTile(xpos,ypos,map(xpos,ypos,ActiveLayer),map(xpos,ypos,LayerCollision))
				map(xpos,ypos,activelayer) = 0
										
			Case LayerObject,LayerBlock,LayerDetail,LayerTop
				undoTile(xpos,ypos,map(xpos,ypos,ActiveLayer),map(xpos,ypos,LayerCollision))
				map(xpos,ypos,ActiveLayer) = 0									

		End Select
	EndIf		

; NB: removed promotion of base tile to top tile (SPACE) as they now have different tilesets!

	If KeyDown(KEY_ENTER) Then activetile = map(xpos,ypos,activelayer)-1 ; pick up tile (RETURN)

	If KeyDown(KEY_NUMPAD_4) ; place 4 concurrent tiles in a square (NUMPAD4!)
		; TODO: Undo in here
		map(xpos,ypos,activelayer)=activetile+1
		map(xpos+1,ypos,activelayer)=activetile+2
		map(xpos,ypos+1,activelayer)=activetile+3
		map(xpos+1,ypos+1,activelayer)=activetile+4
	EndIf		

End Function

Function handlePalette(layer,mouseover)
Local StartX=400	
	mz = MouseZSpeed()
	
	;select the tileset to show in the palette	
	Select layer
		Case LayerBase, LayerBlock
			tileset=btiles : maxtile=bmaxtile
		Case LayerObject	
			tileset=objects : maxtile=NumDefaultObjects
		Case LayerDetail,LayerTop
			tileset=dtiles : maxtile=dmaxtile
		Case LayerCollision,LayerHits
			If Button(Startx+40,610,100,"Static",coll_tool=1,False,KEY_S,"Set tiles to be indestructible walls, vis blocking with Left Control") Then 	coll_tool=1
			If Button(Startx+150,610,100,"Dynamic",coll_tool=2,False,KEY_D,"Set tiles to be destructible walls, vis blocking with Left Control") Then 	coll_tool=2
			If Button(Startx+260,610,100,"Vis-Blocker",coll_tool=3,False,KEY_V,"Set tiles to be barriers to vis checking") Then 	coll_tool=3	
			If Button(Startx+370,610,100,"Hit Points",coll_tool=4,False,KEY_H,"Set tiles to be barriers to vis checking, faster with Left Control") Then 	coll_tool=4								
			Return 
		Default
			Return ; no point hanging around - there's no relevant palette!
	End Select
	
	; active tile	
	Button(835,590,28,activetile+1,False,False,KEY_NONE,"The ID of the currently selected tile")			
	Color 255,255,255:Text 1,1, "Grisu's Xtra LARGE Editor";: "+MouseX()+":"+MouseY()
	;draw the palette itself
	For n=0 To 129
		tileno = n + tileoffset
		If layer=LayerObject Then
			If tileno<maxtile Then
				DrawBlock tileset,((n-(Floor(n/26)*26))*32)+32,610+(Floor(n/26)*32),Abs(objectdef(n+tileoffset+1)\image)				
			ElseIf tileno=maxtile Then
				DrawBlock tileset,((n-(Floor(n/26)*26))*32)+32,610+(Floor(n/26)*32),39 ; 39 is the SPECIAL tile				
			End If
		Else
			If tileno<maxtile Then DrawBlock tileset,((n-(Floor(n/26)*26))*32)+32,610+(Floor(n/26)*32),n+tileoffset
		End If		
		If tileno = activetile Then Color 0,255,0:Rect ((n-(Floor(n/26)*26))*32)+32,610+(Floor(n/26)*32),32,32,False
	Next

	; move around the palette
	tup=0

	;I know it looks like there is nothing in the quotes in the line below, but trust me, there is
	If (Button (0,610,32,"­",False,True,KEY_PAGE_UP,"Scroll up the tileset",False)=True Or (mz = 1 And MouseOver)) And tileoffset > 0 And scrolldelay<0 Then tup=-1
	If (Button (0,630,32,"¯",False,True,KEY_PAGE_DOWN,"Scroll down the tileset",False)=True Or (mz = -1 And MouseOver)) And scrolldelay<0 Then tup=1
	If KeyDown(KEY_NUMPAD_0) And scrolldelay<0 Then activetile = activetile +1:scrolldelay=10
	If KeyDown(KEY_CTRL_RIGHT) And scrolldelay<0 Then activetile = activetile -1:scrolldelay=10
	If tup<>0 Then tileoffset=tileoffset + (tup*26):scrolldelay=15		

	; handle mouse being over the palette
	If mouseover Then
		If MouseDown(1) Then 
			checktile = (Floor((MouseX()-32)/32))+(Floor((MouseY()-610)/32)*26)+tileoffset
			If (checktile < maxtile) And (checktile >-1) Then activetile = checktile
			;If currentRoom<>Null And scrolldelay<0 Then UpdateRoomBlock()	<-removed in changing how room tiles are selected
		ElseIf MouseDown(2)
			If Layer=layerObject And (First objdef<>Null)
				checktile = (Floor((MouseX()-32)/32))+(Floor((MouseY()-610)/32)*26)+tileoffset
				If (checktile < maxtile) And (checktile >-1) Then activetile2 = checktile
				If (activetile2+1) =< numDefaultObjects
					For n=1 To CountString(objectdef(activetile2+1)\trigger,"|")
						trigger$=parse(objectdef(activetile2+1)\trigger,"|",n)
						newdef$ = InputBox("New Script for trigger: '"+trigger+"'. ESC or RETURN to end",20,20,500,300,True,objectdef(activetile2+1)\script[n])
						If Len(newDef) > 0 Then objectdef(activetile2+1)\script[n] = newdef$
					Next														
				EndIf
			EndIf 		
		Else
			; move your mouse over it
			If Layer=layerObject And (First objdef<>Null)
				checktile = 1+(Floor((MouseX()-32)/32))+(Floor((MouseY()-610)/32)*26)+tileoffset
				If (checktile <= maxtile) And (checktile >0) Then 				
					If objectdef(checktile)<>Null
						w=400
						count=CountString(objectdef(checktile)\trigger,"|")
						h=80+(20*(count+1))
						Color 60,60,60:Rect 12,13,w,h,1:Rect 13,13+h,StringWidth("MB2 to edit")+5,FontHeight(),1
						Color 255,255,255 : Rect 10,10,w,h,1 : Rect 10,10+h,StringWidth("MB2 to edit")+5,FontHeight(),1
						Color 0,0,0 : Rect 10,10,w,h,0 : Rect 10,10+h,StringWidth("MB2 to edit")+5,FontHeight(),0
											
						Text 20,20,"Object: "+objectdef(checktile)\name
						Text 20,40,"Image: "+objectdef(checktile)\image
						Text 20,60,"Trigger: "+objectdef(checktile)\trigger
						For n=1 To CountString(objectdef(checktile)\trigger,"|")
							Text 20,80+(n*20),objectdef(checktile)\script[n] 
						Next
						
						Text 12,10+h,"MB2 to edit"
					End If
				ElseIf checktile=maxtile+1 Then
					w=400
					h=100					
					Color 60,60,60:Rect 12,13,w,h,1
					Color 255,255,255 : Rect 10,10,w,h,1
					Color 0,0,0 : Rect 10,10,w,h,0 
											
					Text 20,20,"Special Object: Not implemented yet!"						
				EndIf
			EndIf
		EndIf	
	EndIf
End Function

Function handleRoom()	
		
		;draw mini room
		rx=GraphicsWidth()-150
		ry=GraphicsHeight()-240
		drawRoom(rx,ry)
						
		; new room
		If Button(GraphicsWidth()-50,ry,48,"New",False)
			createBlankRoom():Delay 200 ; stop fast re-clicking	
				
		; load room					
		ElseIf Button(GraphicsWidth()-50,ry+20,48,"Load",False)
			; load the listbox containing possible rooms.
			num=ListDlg(rx-200,ry-230,180,330,room_list)
			If num<>-1
				which$=SL_Strings(room_list,num)			
				If Instr(which,".room")<>0
					quickLoadRoom(which)
				EndIf
			EndIf
			Delay 200 	
			
		; save room
		ElseIf Button(GraphicsWidth()-50,ry+40,48,"Save",False)
			saveRoom():Delay 200		
		EndIf

		; draw room
		If xpos>-1 Then
			If MouseDown(1)
				If create_a_room_sx=-1 And create_a_room_sy=-1
					;DebugLog "setting up room..."
					create_a_room_sx=xpos
					create_a_room_sy=ypos
				EndIf
			Else
				If create_a_room_sx<>-1 And create_a_room_sy<>-1
					;DebugLog "Creating room..."
					; ready to finish.					
					createRoomHere(create_a_room_sx,create_a_room_sy,xpos,ypos)	
					create_a_room_sx=-1
					create_a_room_sy=-1										
				EndIf
			EndIf	
		Else
			create_a_room_sx=-1		
			create_a_room_sy=-1		
		End If
		
		; draw other GUI elements
		If create_a_room_sx=-1 And create_a_room_sy=-1
			statusMsg("Use LMB on map to start top left corner of a room, and drag and release to size",0)
			; tile highlighter
			Color 0,55,0
			x=(xpos-Floor(sc_x/32))*32:y=(ypos-Floor(sc_y/32))*32
			Line x,y,x+32,y
			Line x,y,x,y+32			
		Else
			Button(2,510,28,create_a_room_sx)
			Button(2,530,28,create_a_room_sy)				
			Button(2,550,28,Int(Abs(create_a_room_sx-xpos)+1))
			Button(2,570,28,Int(Abs(create_a_room_sy-ypos)+1))
			; tile highlighter
			Color 0,255,0
			x=(xpos-Floor(sc_x/32))*32:y=(ypos-Floor(sc_y/32))*32
			Line x+32,y,x+32,y+32
			Line x,y+32,x+32,y+32
			Line create_a_room_sx*32-sc_x, create_a_room_sy*32-sc_y, 32+create_a_room_sx*32-sc_x, create_a_room_sy*32-sc_y
			Line create_a_room_sx*32-sc_x, create_a_room_sy*32-sc_y, create_a_room_sx*32-sc_x,    32+create_a_room_sy*32-sc_y					
		EndIf
		
End Function


Function handleFileMenu()
Local Startx=720, Starty=640, Startx2=260, Starty2=290 
		; FILE TOOLS

		If Button(Startx,Starty,140,"New",False,False,KEY_F8,"Create a new map") Then createRandomMap()
		
		If Button(Startx,Starty+20,140,"Save",False,False,KEY_F1,"Save the current map") Then
			FileName$ = InputBox("Enter filename to save (without .map extension)",Startx2+200,Starty2+300,400,40,True,"maps")
			If Len(FileName) <1 Then Return
			If FileType(FileName) = 2 Then Return
			If Instr(filename,".map") Then Replace(filename,".map","")
			save(filename)
			;Save last file name
			fileout = WriteFile("prefs.txt")
				WriteString fileout,FileName$
			CloseFile(fileout)		
		End If
		
		If Button(Startx,Starty+40,140,"Load",False,False,KEY_F4,"Load an existing map") Then 
			FileName$ = InputBox("Enter filename to load (without .map extension)",Startx2+200,Starty2+300,400,40,True,"maps")
			If Instr(filename,".map") Then Replace(filename,".map","") ; just in case
			load(filename) ; call common load.
			moveToStartPosition()		
			DebugLog "Loaded: " + FileName$
			statusMsg("Loaded: " + FileName$)
		End If
		If Button(Startx,Starty+60,140,"Load Last",False,False,KEY_F5,"Load the last edited map") Then
			FileIn = ReadFile("prefs.txt")
				FileName$ = ReadString(FileIn)
			CloseFile(FileIn)
			If Len(FileName$) > 0 Then Load(FileName$):	moveToStartPosition()
		End If
End Function

Function moveToStartPosition()

	; find a start position and move the screen there
	For i=0 To 254
		For j=0 To 254
			tile=map(i,j,LayerObject)
			If tile>0
				For k=0 To 5
					script$=Lower(objectdef(tile)\script[k])										
					If Instr(script,"positionplayer")						
						; we've found it...
						sc_x=((i-10)*32)
						sc_y=((j-10)*32)
						Return
					EndIf
				Next
			EndIf
		Next
	Next
End Function


Map.bb
; map.bb
; Last Modified by Grisu 11/09/04

; recently moved from editor include.bb
Global dmaxtile 				= 0 ;set in loadGraphics below
Global dmaxobject 			= 0
Global bmaxtile 				= 0 ;set in loadGraphics below
Global bmaxobject 			= 0
Global dtiles,btiles,objects,cursor,tiles_small
Global maxobject
Global NumDefaultObjects,NumLevelObjects
Global use_overlay_layer=True

Function loadGraphics$()
	; load tiles
	img=LoadImage("gfx/base.png")
	bmaxtile=(ImageWidth(img)/32)*ImageHeight(img)/32
	FreeImage img
	btiles = LoadAnimImage("gfx/base.png",32,32,0,bmaxtile)
	
	img=LoadImage("gfx/detail.png")
	dmaxtile=(ImageWidth(img)/32)*ImageHeight(img)/32
	FreeImage img
	dtiles = LoadAnimImage("gfx/detail.png",32,32,0,dmaxtile)
	MaskImage dtiles,255,0,255	
	
	; load objects
	img=LoadImage("gfx/objects.png")
	maxobject=(ImageWidth(img)/32)*ImageHeight(img)/32
	FreeImage img
	objects = LoadAnimImage("gfx/objects.png",32,32,0,maxobject)
	MaskImage objects,255,0,255
	
	; load small tiles
	;tiles_small = LoadAnimImage("gfx/tiles_small.png",16,16,0,maxtile)
	;MaskImage tiles_small,255,0,255
	
	cursor = LoadImage("gfx/cursor.png")
	MaskImage cursor,255,0,255	
	font=LoadFont("tahoma.ttf",10):SetFont(font)		
End Function


; load the map in
; load the map in
Function Load(filename$)

	If FileType(FileName$+".map") = 1
		filein = ReadFile(FileName$+".map")
		For layer = 0 To NumLayers
			;If layer<>LayerDetail
				For x=0 To 255
					For y=0 To 255
						map(x,y,layer)= ReadInt(filein)
					Next
				Next
			;EndIf
		Next
		CloseFile filein
	Else
		DebugLog "Filename does not exist: " + FileName$+".map"
	EndIf

	NumDefaultObjects=LoadObjectFile("maps\default")
	NumLevelObjects=LoadObjectFile(FileName$,MAX_DEFAULT_OBJECTS)
		
End Function


;;;;;;;;;;;;;;;;;;;;;;;;;;;
; FUNCTION LoadObjectFile ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;
Function LoadObjectFile(FileName$,startid=1)
	;load the object file
	filename=Replace(filename,".map","")
	
	If startid=1 Then Delete Each objdef
		
	If FileType(FileName$+".obj") = 1
		filein = ReadFile(FileName$+".obj")
		num=parse(ReadLine(filein),"=",1)		
		ReadLine(filein) ; blank space
		If num>0 Then
			;Dim objectdef.objdef(startid+num)
			If startid+num>MAX_OBJECTS Then num=MAX_OBJECTS-startid:DebugLog "Tried too load too many objects!  Trimmed object list to "+MAX_OBJECTS			
			For i=startid To startid+num
				objectdef(i)=New objdef
				objectdef(i)\image=Trim(parse(ReadLine(filein),"=",1))				
				objectdef(i)\trigger=Trim(parse(ReadLine(filein),"=",1))			
				;add a separator to the start to make searching simpler
				If Left(objectdef(i)\trigger,1)<>"|" Then objectdef(i)\trigger="|"+objectdef(i)\trigger
				objectdef(i)\name=Trim(parse(ReadLine(filein),"=",1))			
				
				For n=1 To CountString(objectdef(i)\trigger,"|")
					objectdef(i)\script[n]=ReadLine(filein)
				Next
				ReadLine(filein); blank space
			Next
		End If
		DebugLog num+" objects loaded from "+FileName+".obj"
		CloseFile filein
	Else
		DebugLog "Filename does not exist: " + FileName$+".obj"
	EndIf	
	Return num
End Function


Function Save(filename$)
	fileout = WriteFile(FileName+".map")
	For layer = 0 To NumLayers
		For x=0 To 255
			For y=0 To 255
				WriteInt(fileout,map(x,y,layer))
			Next
		Next
	Next
	CloseFile fileout
	
	saveObjectFile("maps\default",1,NumDefaultObjects)
	SaveObjectFile(filename$,MAX_DEFAULT_OBJECTS,NumLevelObjects)
	
End Function

Function SaveObjectFile(filename$,startid,num)
	; save the object definition file
	fileout = WriteFile(FileName+".obj")
	WriteLine fileout,"total objects = "+num ; number of objects
	WriteLine fileout, "" ; blank line
	For i=startid To startid+num-1
		WriteLine fileout, "image = "+objectdef(i)\image
		WriteLine fileout, "trigger = "+Mid(objectdef(i)\trigger,2) ; chop off the first | for saving
		WriteLine fileout, "description = "+objectdef(i)\name		
		For n=1 To CountString(objectdef(i)\trigger,"|")
			WriteLine fileout,objectdef(i)\script[n] 
		Next
		WriteLine fileout,"" ; blank line
	Next
	CloseFile fileout
End Function

; Get tile gets the tile under x,y (pixels) world co-ordinates
Function gettile(x,y,layer)
	; sort out the block location based on pixel co-ord
	x = Floor(x/32)
	y = Floor(y/32)
	; the following four lines should be unnecessary!
	If x < 0 Then Return
	If y < 0 Then Return
	If x > 255 Then Return
	If y > 255 Then Return
	Return map(x,y,layer)
End Function

Function puttile(x,y,layer,newtile)
	x = Floor(x/32)
	y = Floor(y/32)
	; the following four lines should be unnecessary!
	If x < 0 Then Return
	If y < 0 Then Return
	If x > 255 Then Return
	If y > 255 Then Return	
	map(x,y,layer)=newtile
End Function


Function opendoor(x,y,vis=True)
	id%=map(x,y,LayerObject)
	If id=0
		RuntimeError("Function Map->OpenDoor("+x+","+y+","+vis+")"+Chr(13)+"has tried to access a tile with nothing in it.")
	EndIf
	
	
	map(x,y,LayerObject)=0 ; set to 0
	map(x,y,LayerCollision)=0
	
	If map(x,y-1,LayerObject)=id Then opendoor(x,y-1,False)
	If map(x,y+1,LayerObject)=id Then opendoor(x,y+1,False)
	If map(x+1,y,LayerObject)=id Then opendoor(x+1,y,False)
	If map(x-1,y,LayerObject)=id Then opendoor(x-1,y,False)

	; check the vis from this newly opened door!
	If vis Then CheckVis(x,y)	
End Function



Function drawmap(xpos,ypos,layer,ineditor=False)
; This function draws the map
; NB: for all "if ___ then Draw ___" lines, multiply the expression by map(x+xoff,y+yoff,LAYER_VISIBLE)
; determine sizes
blocksize=32
min_x=-1
min_y=-1
If ineditor Then
	max_x=26
	max_y=17
Else
	max_x=20
	max_y=16
EndIf

; sort out the block location based on pixel co-ord
xoff = Floor(xpos/blocksize)
yoff = Floor(ypos/blocksize)

; find the pixel offset
xpxoff = (xoff * blocksize) - xpos
ypxoff = (yoff * blocksize) - ypos

; limit tile drawing are to map size
If xoff<=0 Then min_x=-xoff
If yoff<=0 Then min_y=-yoff
If xoff>255-max_x Then max_x=255-xoff
If yoff>255-max_y Then max_y=255-yoff

; draw base layer
; uses draw block so you don't need a cls and is quicker.
If layer = LayerBase
	For x = min_x To max_x
		For y = min_y To max_y
;			If x+xoff>=0 And y+yoff>=0 And x+xoff<=255 And y+yoff<=255
				If map(x+xoff,y+yoff,layer)>0 Then
					If map(x+xoff,y+yoff,LAYER_VISIBLE)>0 Or ineditor Then DrawBlock btiles,(x*blocksize)+xpxoff,(y*blocksize)+ypxoff,map(x+xoff,y+yoff,layer)-1
				EndIf
;			EndIf
		Next
	Next
EndIf

If layer = LayerObject
	For x = min_x To max_x
		For y = min_y To max_y 
;			If x+xoff>=0 And y+yoff>=0 And x+xoff<=255 And y+yoff<=255
				tile=map(x+xoff,y+yoff,layer)
				If tile>0 Then
					If ineditor Then 
						img=Abs(objectdef(tile)\image)
					Else 
						If map(x+xoff,y+yoff,LAYER_VISIBLE)>0 Then img=objectdef(tile)\image Else img=-1
					End If
					If img>=0 Then DrawImage objects,(x*blocksize)+xpxoff,(y*blocksize)+ypxoff,img
				EndIf
;			EndIf
		Next
	Next
EndIf

; draw other layers
If layer = LayerTop And use_overlay_layer
	For x = min_x To max_x
		For y = min_y To max_y
;			If x+xoff>=0 And y+yoff>=0 And x+xoff<=255 And y+yoff<=255			
				If map(x+xoff,y+yoff,layer)>0 Then 
					If map(x+xoff,y+yoff,LAYER_VISIBLE)>0 Or ineditor Then DrawImage dtiles,(x*blocksize)+xpxoff,(y*blocksize)+ypxoff,map(x+xoff,y+yoff,layer)-1		
				End If
;			EndIf
		Next
	Next
EndIf

; layer 4, block overlay no transparancy
If layer = LayerBlock
	For x = min_x To max_x
		For y = min_y To max_y
;			If x+xoff>=0 And y+yoff>=0 And x+xoff<=255 And y+yoff<=255			
				If map(x+xoff,y+yoff,layer)>0 Then 
					If map(x+xoff,y+yoff,LAYER_VISIBLE)>0 Or ineditor Then DrawBlock btiles,(x*blocksize)+xpxoff,(y*blocksize)+ypxoff,map(x+xoff,y+yoff,layer)-1			
				End If
;			EndIf
		Next
	Next
EndIf

; detail overlay
If layer = LayerDetail
	For x = min_x To max_x
		For y = min_y To max_y
;			If x+xoff>=0 And y+yoff>=0 And x+xoff<=255 And y+yoff<=255		
				If map(x+xoff,y+yoff,layer)>0
					If map(x+xoff,y+yoff,LAYER_VISIBLE)>0 Or ineditor Then DrawImage dtiles,(x*blocksize)+xpxoff,(y*blocksize)+ypxoff,map(x+xoff,y+yoff,layer)-1						
				EndIf
;			EndIf
		Next
	Next
EndIf


If layer = LayerHits And ineditor
	Color 255,255,255
	For x = min_x To max_x
		For y = min_y To max_y
;			If x+xoff>=0 And y+yoff>=0 And x+xoff<=255 And y+yoff<=255	
				If map(x+xoff,y+yoff,layer)=-1 Then Text (x*32)+8,(y*32)+8,map(x+xoff,y+yoff,layer),True
				If map(x+xoff,y+yoff,layer)>0 Then Text (x*32)+8,(y*32)+8,map(x+xoff,y+yoff,layer),True
;			End If
		Next
	Next
EndIf

If layer=LayerCollision And ineditor
	For x=min_x To max_x
		For y=min_y To max_y
;			If x+xoff>=0 And y+yoff>=0 And x+xoff<=255 And y+yoff<=255	
				Select map(x+xoff,y+yoff,LayerCollision ) 
				Case czStatic
					Color 255,0,0
					Rect (x*32)+7,(y*32)+7,18,18,False
				Case czDynamic
					Color 0,255,0
					Rect (x*32)+7,(y*32)+7,18,18,False
				Case czVisStatic
					Color 255,255,255
					Rect (x*32)+8,(y*32)+8,16,16,False
					Color 255,0,0
					Rect (x*32)+7,(y*32)+7,18,18,False			
				Case czVisDynamic
					Color 255,255,255
					Rect (x*32)+8,(y*32)+8,16,16,False	
					Color 0,255,0
					Rect (x*32)+7,(y*32)+7,18,18,False					
				Default
					;do nothing
				End Select
;			End If
		Next
	Next
End If

End Function

; list of tiles to check for visibility
Type vis_list
	Field x,y
End Type

Function CheckVis(x,y)
; This function determine the map vis for a player
	; add the start tile to the list
	v.vis_list=New vis_list
	v\x=x
	v\y=y

	; and start checking by looping through all tiles in the list that need checking
	Repeat
		; go through all 8 nearby squares
		For i=1 To 8
			Select i
				Case 1:x=v\x-1:y=v\y-1
				Case 2:x=v\x-1:y=v\y
				Case 3:x=v\x-1:y=v\y+1
				Case 4:x=v\x:y=v\y-1
				Case 5:x=v\x:y=v\y+1
				Case 6:x=v\x+1:y=v\y-1
				Case 7:x=v\x+1:y=v\y
				Case 8:x=v\x+1:y=v\y+1
			End Select
			
			; if it's on the map, we check it
			If x>=0 And x<=255 And y>=0 And y<=255 Then
				; if it's never been checked before (vis=0), check it.  otherwise, don't bother
				If map(x,y,LAYER_VISIBLE)=0 Then

					; set it to visible (including all solid blocks at the boundary of vis are themselves visible)
					map(x,y,LAYER_VISIBLE)=1
				
					; and provided it's not a vis stop, add it to the list of tiles to process
					If map(x,y,0)<czVisStatic  Then
						nv.vis_list=New vis_list
						nv\x=x
						nv\y=y
					End If
				End If
				
			End If	
					
		Next
		
		; set current tile to visible
		map(v\x,v\y,LAYER_VISIBLE)=1
				
		; eliminate this one from the list to check and move on to the next one
		Delete v
		v=First vis_list
	Until v=Null
		
End Function

Function ClearVis()
	;set initial visibility for all tiles to none at all
	;we'll set initial player vis when we create the player
	For x=0 To 255
		For y=0 To 255
			map(x,y,LAYER_VISIBLE)=0
		Next
	Next
End Function


Gui.bb
;Global font = LoadFont("Arial.ttf",15)
;Global symbFont = LoadFont("Symbol.ttf",15)

Include "inc\stringlist.bb"
Dim CharWidths(1)

Const KeyRepeat% = 100
Const CaratSymbol$ = "¦"

Type TRGB
	Field ColRed%
	Field ColGreen%
	Field ColBlue%
End Type


Global myRGB.TRGB = New TRGB

Type TCarat
	;X and Y in characters not pixels
	Field X%
	Field Y%
	Field PX%
	Field PY%
	Field Symbol$ = "¦"
End Type

Type TKeyState
	Field Scancode%
	Field Ascii%
	Field Shift
	Field Ctrl
End Type


Type TLine
	Field LineNum%
	Field Txt$
	Field Owner$
End Type


;;;;;;;;;;;;;;;;;;;;
; FUNCTION InitGUI ;
;;;;;;;;;;;;;;;;;;;;
Function InitGUI()

	SetFont font

;INPUT BOX SETUP
;Get the character widths
Dim charwidths(512)
	charwidths(32) = 4
	For c = 33 To 512
		charwidths(c) = StringWidth(Chr$(c))
	Next
End Function


;;;;;;;;;;;;;;;;;;;
; FUNCTION Button ;
;;;;;;;;;;;;;;;;;;;

Function Button(x,y,width,name$,active=False, symbol=False, ShortCutKey=KEY_NONE,tip$="", ShowShortCut = True, OffCol%=$A0A0A0,  OverCol%=$C8C8C8, TextCol%=$000000)
;VARS
	Local result = False
	
;MAIN

	If (ShortCutKey > KEY_NONE)  Then 
		If ShowShortCut Then name = name + " ("+ KeyNames(ShortCutKey) +")"
		tip$ = tip$ + " ("+ KeyNames(ShortCutKey) +")"		
	EndIf
		
	If RectsOverlap(MouseX(),MouseY(),1,1,x,y,width,16) Then 
		myRGB = GetRGB(OverCol)
		Color myRGB\ColRed, myRGB\ColGreen, myRGB\ColBlue
		tooltip(MouseX(),MouseY(),tip$)
	Else 
		myRGB = GetRGB(OffCol)
		Color myRGB\ColRed, myRGB\ColGreen, myRGB\ColBlue
	EndIf
	Rect x,y,width,16

	myRGB = GetRGB(TextCol)
	Color myRGB\ColRed, myRGB\ColGreen, myRGB\ColBlue


	If Symbol Then SetFont symbFont

	Text x+width/2,y+7,name,True,True

	If Symbol Then SetFont Font

	If active Then Color 255,0,0:Rect x,y,width,16,False
	If RectsOverlap(MouseX(),MouseY(),1,1,x,y,width,16) And MouseDown(1) Then result = True

	If ShortCutKey > KEY_NONE Then
		If KeyDown(ShortCutKey) Then Result = True
	EndIf

	Return Result
	
End Function 



;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; FUNCTION InputBox									 ;
; Parameters:                                        ;
; msg$ : any message to display above the input box  ;
; x,y : top left coords                              ;
; width, height: outer width and height of inputbox  ;
; rtnSubmit : if the return key is pressed, then     ;
;             automatically submit the text			 ;
;             If this is false, then an OK button is ;
;             displayed at the bottom of the box     ;
; DefaultText : automatically inserts this into the  ;
; input box, the carat will be positioned at the end ;
; of this text.                                      ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

Function InputBox$(Msg$,x,y,width,height,rtnSubmit=True, DefaultText$="", BGCol%=$FFFFFF, TextCol%=$000000, BorderCol%=$A0A0A0)

	SetFont Font

;;;;;;
;vars;
;;;;;;

	Local leave = False
	Local InnerWidth = Width - 6
	Local InnerHeight = Height - 40
	Local InnerX = 6
	Local InnerY = 20
	Local retString$ = ""
	Local fntWidth = FontWidth()/4
	Local fntHeight = FontHeight()
	Local EditWin = CreateImage(width, height)
	Local BGImage = CreateImage(GraphicsWidth(), GraphicsHeight())
	Local Delimiters$ = "|() "+Chr$(13)
	Local FoundDelim = False
	Local TopLine = 0
	
	Local Carat.TCarat = New TCarat
			Carat\X = 0
			Carat\Y = 0

	Local SelStart% = 0 
	Local SelEnd% = 0
	Local CaratPos% = 0
	
	Local ScrollPos = 0
	
	Local ScrollWidth = 12

;;;;;;
;main;
;;;;;;

CopyRect 0,0,GraphicsWidth()-1, GraphicsHeight()-1, 0,0, GraphicsBuffer(), ImageBuffer(BGImage)

If rtnSubmit Then InnerHeight = Height - 6
FlushKeys()
CaratPos = Len(DefaultText)
retString = retString+DefaultText

Repeat
	;quit the function without returning any text if escape is pressed
	If KeyHit(1) Then 
		leave = True
		retString$ = ""
	EndIf
	
	;;;;;;;;;;;;;;;;;;;;;
	;get character input;
	;;;;;;;;;;;;;;;;;;;;;
	get = GetKey()
	
	
	
	If Get = 13 Then
		If rtnSubmit Then 
			leave = True ;if return is pressed and rtnSubmit is True then leave
		Else
			LeftSide$ = Left$(retString$,CaratPos)
			RightSide$ = Right$(retString$, Len(RetString)-CaratPos)
			retString$ = LeftSide$ + Chr(get) + RightSide$
			CaratPos = CaratPos + 1
		EndIf
	ElseIf KeyDown(14); backspace
		If MilliSecs()-LastInput > KeyRepeat Then
			If Len(retString$) > 0 Then 
				LeftSide$ = Left$(retString$,CaratPos)
				RightSide$ = Right$(retString$, Len(RetString)-CaratPos)
				retString$ = Left$(LeftSide$, Len(LeftSide$) -1) + RightSide$
			EndIf
			LastInput = MilliSecs()
			CaratPos = CaratPos - 1
			If CaratPos < 0 Then CaratPos = 0
		EndIf
	ElseIf KeyDown(203) ;Left Cursor
		If MilliSecs()-LastInput > KeyRepeat Then
		
			If KeyDown(157) ; CTRL ; Allow CTRL+Left to jump the carat pos to the next delimiter to the left of the cursor
				For i = CaratPos To 1 Step -1
					
					d = 1
					While (d < Len(Delimiters$)+1) And (Not FoundDelim )	
						
						If Mid(retString$, i,1) = Mid(Delimiters$, d,1) Then 
							CaratPos = i-1
							FoundDelim = True
						EndIf
						d = d + 1
					
					Wend
				
					If FoundDelim Then Exit
				Next
				
				If Not FoundDelim Then CaratPos = CaratPos - 1
				If CaratPos < 0 Then CaratPos = 0
				
				FoundDelim = False
			
			Else
				CaratPos = CaratPos - 1
				If CaratPos < 0 Then CaratPos = 0
			EndIf
			LastInput = MilliSecs()
		EndIf
	ElseIf KeyDown(205) ; RIGHT CURSOR
		If MilliSecs()-LastInput > KeyRepeat Then
			If KeyDown(157) ;CTRL ; Allow CTRL+RIGHT to jump the carat pos to the next delimiter to the right of the cursor

				For i = CaratPos+1 To Len(retString$)
					d = 1					
					While (d < Len(Delimiters$)+1) And (Not FoundDelim )

						If Mid(retString$, i,1) = Mid(Delimiters$, d,1) Then 
							CaratPos = i
							FoundDelim = True
						EndIf
						d = d + 1
					Wend				

					If FoundDelim Then Exit
				Next
				
				If Not FoundDelim Then CaratPos = CaratPos + 1
				If CaratPos > Len(retString$) Then CaratPos = Len(retString$)
				
				FoundDelim = False
		
			Else
				CaratPos = CaratPos + 1
				If CaratPos > Len(retString$) Then CaratPos = Len(retString$)
			EndIf
			LastInput = MilliSecs()
		EndIf

	ElseIf KeyDown(207) ; end
		CaratPos = Len(retString$)
	ElseIf KeyDown(199) ; home
		CaratPos = 0
	ElseIf (get > 31) ;is a letter, number or symbol

		LeftSide$ = Left$(retString$,CaratPos)
		RightSide$ = Right$(retString$, Len(RetString)-CaratPos)
		retString$ = LeftSide$ + Chr(get) + RightSide$
		CaratPos = CaratPos + 1
		
	EndIf

		
		;Draw the edit window
		oldbuffer = GraphicsBuffer()
		SetBuffer ImageBuffer(EditWin)
			
			myRGB = GetRGB(BorderCol)
			Color myRGB\ColRed, myRGB\ColGreen, myRGB\ColBlue
			Rect 0,0,width,height

			myRGB = GetRGB(BGCol)
			Color myRGB\ColRed, myRGB\ColGreen, myRGB\ColBlue
			Rect 2, 17, InnerWidth , InnerHeight

			myRGB = GetRGB(TextCol)
			Color myRGB\ColRed, myRGB\ColGreen, myRGB\ColBlue
			
			Text width/2,8,msg,True,True
			
			Viewport 2, 17, InnerWidth ,InnerHeight
			
			;Draw Edit Content
			Local WCount% = 0
			Local LineCount% = 0
			Local CharCount% = 0
			Local tempString$ = ""
			;Local tempString2$ = ""
			Local StringLength% = Len(retString$)
			Local CurrentChar$ = ""
			Local LineLength% = 0

			While CharCount < StringLength

				Repeat
					CharCount = CharCount + 1
					Currentchar$ = Mid$(retString$, CharCount,1)	
					If Charcount = CaratPos+1 Then tempString$ = tempString$ + CaratSymbol$
					tempString$ = tempString$ + CurrentChar$
					charWidth = CharWidths(Asc(CurrentChar))
					WCount = WCount + charWidth
				Until (WCount > InnerWidth - 8) Or (CharCount = StringLength) Or (Asc(CurrentChar) = 13)

				If Right$(tempString,1) = Chr(13) Then 
						tempString$ = Left(TempString$,Len(TempString$)-1)
				EndIf

			
				myRGB = GetRGB(TextCol)
				Color myRGB\ColRed, myRGB\ColGreen, myRGB\ColBlue
				If (CaratPos = StringLength) And (CaratPos = CharCount) Then tempString = tempString + CaratSymbol
				Text InnerX,InnerY + (LineCount * fntHeight),tempString$,False,False
				
				LineCount = LineCount + 1
			
				tempString$  = ""

				WCount = 0


			Wend
		
		SetBuffer OldBuffer
	
	DrawBlock BGImage,0,0
	DrawBlock EditWin,x,y	
	
	Viewport 0,0,GraphicsWidth(), GraphicsHeight()
	
	If Not rtnSubmit Then
		If Button(x+(Width/2)-95,y+Height-20,80,"OK",False,False,KEY_INSERT,False,BorderCol,BGCol,TextCol) Then leave = True
		If Button(x+(Width/2)+5,y+Height-20,100,"Cancel",False,False,KEY_ESCAPE,False,BorderCol,BGCol,TextCol) Then
			retString = ""
			leave = True
		EndIf
	EndIf
	
	DrawImage cursor,MouseX()-1,MouseY()-1
	
	Flip

Until leave = True

	FlushKeys()
	FlushMouse()

	

	FreeImage EditWin
	FreeImage BGImage

	Return retString$

End Function


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; FUNCTION GetRGB                            ;
; converts an int to R/G/B colour            ;
; returns a type of TRGB                     ;
; example Usage:                             ;
; myRGB.TRGB = New TRGB                      ;
; myRGB = GetRGB($FF55FF)                    ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

Function GetRGB.TRGB(InColour%)

Local tempRGB.TRGB = New TRGB
	tempRGB\ColRed = InColour% Shr 16 And 255 Shl 0
	tempRGB\ColGreen = InColour% Shr 8 And 255 Shl 0
	tempRGB\ColBlue = InColour% Shr 0 And 255 Shl 0
Return tempRGB

End Function


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; FUNCTION ListBox                       ;
; returns the index of the selected item ;
; parameters:                            ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Function ListDlg%(X%, Y%, Width%, Height%, Items.TStringList,  BGCol%=$FFFFFF, TextCol%=$000000, BorderCol%=$A0A0A0)
;			myRGB = GetRGB(TextCol)
;			Color myRGB\ColRed, myRGB\ColGreen, myRGB\ColBlue

SetFont Font

;;;;;;
;VARS;
;;;;;;

	Local BorderWidth% = 2
	
	Local InnerX% = X + BorderWidth
	Local InnerY% = Y + BorderWidth

	Local InnerWidth% = Width - (BorderWidth * 2)
	Local InnerHeight% = Height - (BorderWidth * 2)

	Local ListWin = CreateImage(Width, Height)
	Local BGImage = CreateImage(GraphicsWidth(), GraphicsHeight())

	Local Selected% = -1
	Local ScrollOffset% = 0
	Local ScrollBarWidth = 12
	Local leave = False
	Local Result = -1
	Local FirstMouseHit = 0
	Local SecondMouseHit = 0
;;;;;;
;MAIN;
;;;;;;

CopyRect 0,0,GraphicsWidth()-1, GraphicsHeight()-1, 0,0, GraphicsBuffer(), ImageBuffer(BGImage)

If SL_GetCount(items) < 1 Then Return -1

While Not Leave

	;check keyboard input
	If KeyHit(1) Then 
		Result = -1
		Leave = True
	EndIf
	
	;28 Or 156 = Return Or Enter
	If KeyHit(28) Or KeyHit(156) Then
		Result=Selected
		Leave = True
	EndIf
	
	;up arrow
	If KeyHit(200) Then 
		selected = selected -1
		If selected < 0 Then selected = 0
	EndIf
	
	;down arrow
	If KeyHit(208) Then 
		selected = selected + 1
		If selected > SL_GetCount(Items)-1 Then Selected = SL_Getcount(Items)-1
	EndIf
	

	;check mouse input
	
	mx = MouseX()
	my = MouseY()

	If (mx > InnerX+2) And (mx < InnerX + (InnerWidth-ScrollWidth-4)) Then
		If (my > InnerY+2) And (my < (InnerY + (InnerHeight-2)) ) Then
			If MouseDown(1) Then			

				Selected = ( ( (my - InnerY) - ScrollOffset) / FontHeight())
				If Selected < 0 Then selected = 0
				If selected > SL_GetCount(Items)-1 Then selected = SL_Getcount(Items)-1

			EndIf
			
			;maybe do a tooltip here if the item the mouse 
			;is over is longer than the width of the list

		EndIf
	EndIf


	;draw listbox

	If SL_GetCount(items) * FontHeight() > InnerHeight Then 
		ScrollBarWidth = 16
	Else 
		ScrollBarWidth = 0
	EndIf
	
	InnerWidth = ((Width - (BorderWidth * 2)) - ScrollBarWidth ) + 4

	oldbuffer = GraphicsBuffer()
	SetBuffer ImageBuffer(ListWin)

	;draw Border
	myRGB = GetRGB(BorderCol)
		Color myRGB\ColRed, myRGB\ColGreen, myRGB\ColBlue
		Rect 0, 0, Width, Height, True

	;Draw background
	myRGB = GetRGB(BGCol)
		Color myRGB\ColRed, myRGB\ColGreen, myRGB\ColBlue
		Rect BorderWidth, BorderWidth, InnerWidth - (BorderWidth*2), InnerHeight - (BorderWidth), True

	;clip to inner rectangle
	Viewport BorderWidth + 2, BorderWidth + 2, InnerWidth-8, InnerHeight-8
	
	;draw the text
	For i% = 0 To SL_GetCount(items)-1
		If i = selected Then
		
			;draw a rect over the selected area
			myRGB = GetRGB(TextCol)
			Color myRGB\ColRed, myRGB\ColGreen, myRGB\ColBlue
			;for some reason, changing the following colour to black (0,0,0), draws as transparent

			;Color 10,10,10
			Rect BorderWidth + 2, (i * FontHeight())+ ScrollOffset, InnerWidth%, FontHeight(), True

			myRGB = GetRGB(BGCol)
			Color myRGB\ColRed, myRGB\ColGreen, myRGB\ColBlue

		Else
			myRGB = GetRGB(TextCol)
			Color myRGB\ColRed, myRGB\ColGreen, myRGB\ColBlue
		EndIf

		Text BorderWidth+2, (i * FontHeight())+ ScrollOffset, SL_Strings(items, i), False, False
	Next
	
	Viewport 0,0,Width,Height
	
	
	SetBuffer oldbuffer
	
	DrawBlock BGImage,0,0
		
	DrawBlock Listwin, x,y


	mz = MouseZSpeed()
  
	If Button (X + Width - ScrollBarWidth, y + BorderWidth, 12, "­", False, True) Or mz = 1 Then
		;scroll up
		ScrollOffset = ScrollOffset + FontHeight()
		If ScrollOffset > 0 Then ScrollOffset = 0
	EndIf
	
	If Button (x + Width - ScrollBarWidth, (y + Height - FontHeight()) - BorderWidth, 12, "¯", False, True) Or mz = -1 Then
		;scroll down
		ScrollOffset = ScrollOffset - FontHeight()
		If ScrollOffset < -( (SL_GetCount(Items)-1) * FontHeight()) Then ScrollOffset = -( (SL_GetCount(Items)-1) * FontHeight())
	EndIf


	If selected > -1 Then s$ = SL_Strings(items, selected)
	If StringWidth(s$)>InnerWidth-4 Then 
		tooltip(InnerX+2,InnerY + (Selected * FontHeight())+ScrollOffset,s$)
	EndIf

	DrawToolTip()

	DrawImage cursor,MouseX()-1,MouseY()-1

	Flip

Wend

FreeImage ListWin
FreeImage BGImage

Return result

End Function

;;;;;;;;;;;;;;;;;;;;
; FUNCTION ToolTip ;
;;;;;;;;;;;;;;;;;;;;

Global tt_txt$,tt_currtxt$,tt_x,tt_y,tt_w,tt_h,tt_starttime%
Const tt_waittime%=500

Function ToolTip(x,y,txt$)
	tt_txt$=txt$
	tt_w=StringWidth(txt$)+4
	tt_h=FontHeight()+4
	If x+tt_w+4>GraphicsWidth() Then tt_x=GraphicsWidth()-tt_w Else tt_x=x
	If y+tt_h+4>GraphicsHeight() Then tt_y=GraphicsHeight()-tt_h Else tt_y=y
End Function

Function DrawToolTip()
	If tt_txt$<>"" Then 
		If tt_txt$ = tt_currtxt$ Then
			; only actually draw it if we've exceed the wait time
			If tt_starttime+tt_waittime<MilliSecs() Then
				Color 255,255,225
				Rect tt_x,tt_y,tt_w,tt_h,True
				Color 0,0,0
				Rect tt_x,tt_y,tt_w,tt_h,False
				Text tt_x+2,tt_y+2,tt_txt$
			End If
		Else
			; if it's a new tooltip, reset the timer
			tt_starttime=MilliSecs()
		End If
	End If
	tt_currtxt$=tt_txt$	
	tt_txt$=""
End Function

;;;;;;;;;;;;;;;;;;;
; Status Messages ;
;;;;;;;;;;;;;;;;;;;

Type statusMsg
	Field msg$,life
End Type

Function statusMsg(mr$,lifetime=100)
	If lifetime=0 Then Delete Each statusMsg
	m.statusMsg=New statusMsg
	m\msg=mr
	m\life=lifetime
End Function

Function drawStatusBar()
	o.statusMsg=First statusMsg
    If o <> Null
	Color 0,0,0	
    Rect 3,GraphicsHeight()-14,(Len(o\msg)*7),14,1
    EndIf 
	If o = Null
		Color 0,0,0	
        Rect 3,GraphicsHeight()-14,(12*7),14,1
    	Color 255,255,255	
		txt$=txt+"Undo Level: "+countUndos()
	Else
		; draw the status message here...
    	Color 255,255,255	
		txt$=o\msg
		o\life=o\life-1
		If o\life < 0 Then Delete o
	EndIf
	Text 3,GraphicsHeight()-14,txt
End Function


Nice stuff Grisu, I'll upload this when we've got some more changes. The editor looks a touch empty now.

I hope you don't mind but I got rid of your Grisu advert off the screen (don't worry you'll be in the credits!), sorry but it was annoying me! And I moved the XY co-ords so they didn't overlap the edit area.

As, you like: the text msg was for debug reasons only... :)

Where did u move the x,y coords... I'm thinking of rearranging the menu.. in order to maximise usability.

What do u think of this:
[Codebox]http://legion.gibbering.net/grisu/edt.jpg[/Codebox]

Still needs some work as I need to replace some menus...

This way we have less empty space, but cant add more main menu buttons!

Cool, Works for me!

ok, will code on that then.

Don't include stuff till I'm done...

P.S: I'm the master of optimising stuff to death. :D

If you want to optimise, then do it in the main game engine not the editor, the game engine is what will require more focus.

Code Update:
http://legion.gibbering.net/grisu/grisu.zip

+ added: Tile Palette button to switch between "Room Editor" and back
% Reaffanged all menus
% enlarged map view
% fixed gui msg bg

Still adding stuff...

! Only problem "When selecting Object layer the tiles are messed up and i can't find out why... Perhaps u can... :( !

1. Ahm, I have a question for the Room Tool (editor).
Are rooms always 3x3 tiles as in the tool win?
Could you write me a plain function, that just loads a given filename and outputs it on screen at given x,y pos. No array saving and types needed. Simply drawing...

2. With your font system:
Is it possible to draw colorised texts on the "fly"

Changes I'd like to do:
- Menu item currently selected is highlighted light blue
- Credits topic are highlighted blue < >
- Credits fade in at bottom and fade out at top before reaching the logo... white -> light grey -> dark grey -> black

Even heros have to take a break sometimes...



1. The room creator just lets you select the walls and the floor tile, hence the 3x3.

2. No, there's no reason why the bitmap font couldn't be extended as it's only a 50x50 2 colour image. Just paste on new versions of it in different colours, then just offset the frame it draws based on the colour choice. ie Colour 0 (black) colour 1 (blue) would + 100 to the frames, color 2 (green) + 200 etc. Job done and very easy.

3. Go for it. The problem you're going to have is that because it scrolls you'll have to read the pixels, and darkend them, not hard to do but might be a little slow on lower spec machines.

			DrawBlock bg,0,0
			LockBuffer ImageBuffer(scroller)
			For xx=0 To 255
				For yy=1 To 48
					GetRGB(scroller,xx,yy) 
					If gotr>0 Then WriteRGB(scroller,xx,yy,yy*5,yy*5,yy*5)
				Next
			Next
			UnlockBuffer ImageBuffer(scroller)
			DrawBlock scroller,5,80

If you add this bit of code in the credits function in frontend.bb it'll fade the top to black.

I get an integer divide by zero error in aliens.bb at this line:
al\turncounter = (al\turncounter + 1) Mod al\turnspeed
in the Update_Aliens function
This occurs as soon as I open the first door.

*edit*
al\speed is set to 0 as is al\turncounter, I don't know exactly where this is being set.

Have you downloaded the gfx? If not you won't be getting the updated class.txt files on the aliens... and you'll get divide by zero. They're both being set in then spawnalien() function. The class files now contain..
<turnspeed>5</turnspeed> ;  how fast the alien turns around


1. Rob, have u checked my prob with the object layer selection in the editor yet?

2. Could you add a filedate to the downloadable files, so we know when new source is up?!?

1. No, your last one worked fine... Not had time. Mark's probably the person to look at it though as he's currently the editor king! He's been doing clever stuff with the object layer (disconnecting objects with graphics) so he'll probably be able to sort whatever problem there is.
2. I let you know when the source is up by saying zips updated in the thread! It's a pain in the arse dating it each time... I'll see what I can do though.

I've updated the bitmap font routine so there's white, blue and red font colours. It's called in the same way but you just add the colour number on the end (0,1 or 2). Also updated the credits so you get your different colours. Taken the fadey bit out as it really slows them down so they don't look smooth.

Drawn a toilet (see above!) Trying to think of more 'real life' things that you'd find in on a base. Kitchen, Bathroom, lounge, Canteen etc and drawing some tiles for them.

Writepixel is really slow in debug and window mode.
On my PC AMD XP 2100 with debug = off it was smooth!
We can reduce the yy value to "For yy=1 To 20", still will look better.
For the smootnness: Instead reading the lines from the file. Pre-chache them at startup in a Dim or type field. That's how I'm doing it in CW!

Sadly. i'm no good artist. - A bar room with snooker table would be nice... :)
Will mess around, perhaps I can contribute some tiles as well...
Don't know if this is already planed, how about elctric fields (animated) that block players path until a switch is hit? Thie could be ground tiles or sidways (door like).
Then you could paint a nice power core, nearly like an Alien II scenario. :)

Will there be some kind of mini map in the later pocket pc?

Have you downloaded the gfx?

Oops! I did download it, but I fogot to extract it to the correct directory.

I've avoided dimming the whole credits into an array as I think it's a crap way of doing it. Could actually use the messenger command to do the credits now... that would look really cool. (fire up the mes_test.bb).

Animated graphics are on their way in... just got to work out how we're going to do it! All that sort of puzzle will arrive. This is why Mark is playing with the editor and objects so much.

I like the idea of a bar room with a snooker table. I also though about having spinny chairs that spin when you shoot them!? I also thought a boiler room would be cool too with lots of pipes and stuff (probably a bit like the power core idea).

There's already a mini map if you log onto the intex systems, press fire 2 (right shift for player 1) next to a console, there's a console in the room you start in. Choose the radar service and you get a mini map. It's kept simple so it doesn't give anything away.

Anyway... Time for bed!

I also though about having spinny chairs that spin when you shoot them!?

How about an OnDamage event and an AnimateObject command?

Animated graphics:

Set different global timers for each animated object that are checked each loop and compared with current time.

"Chair_Spin_Timer=500 (ms)
If current_time=Chair_init_time+Chair_Spin_Timer then
Spinframe=(Spinframe+1)mod spinmaxframe
Chair_init_time=millisecs()
endif

Then just draw the currently selected frame of an object on screen.

The theory of how to do it isn't the issue Grisu, it's the implementation within the current stucture and making it all work, and also being effeciant so it's not handling stuff that's way off screen or not visible. On top of this it has to be implemented into the editor some how and obviously having many graphic sets isn't reasonable for an editor, this is why Mark is dislocating graphics from the objects.

I really don't want global timers as this syncronises everything so nothing looks natural. It'll probably be more like the aliens where you set the animate speed and each item will be handled individually, this way you get a more natural look and not everything animating like marching soliders. Also global timers for each animated object means we would have to know before we compile the code what objects will be animating, this is totally against the grain of the code as we are trying to soft code everything, or at least as much as possible.

Back from the nether-regions of the UK (Glasgow). Just scanned the posts above, sounds you've been doing some good stuff Grisu. I'll download tonight, andhopefully get some good coding time in. Whilst changing the editor, could you steer clear of anything to do with objects : as Rob says, I'm working on that area.

Current thinking is along these lines:
Animated tiles are also objects, not normal tiles. They'll be in the default object list (not the level specific list, although that'll be possible too). The object will have a trigger of something like "ondraw()", and then the script for that trigger will be something like "drawtile(10,5)|drawtile(11,5)|drawtile(12,100)". This will show tile 10 of the detail layer for 5 frames, tile 11 for 5 frames, then tile 12 for 100 frames. (example here being an occassional spark).

In terms of how this works, whenever a tile is drawn, the ondraw trigger will be fired, and this will create a type containing that info, plus it's own frame timer (set to a random time initially). On each drawing loop, check for any such types, click the timer on by one, and if that means the detail tile gets changed, change it. Also, if the tile is no longer visible, delete the type - although we'll want to hang on to instances for a couple of seconds after going off screen in case you come back and find e.g. a fan spinning differently to how it was!

Sounds would work along a similar line, possibly even using the same trigger, but that'll be a bit harder for continuous sounds - one off sounds will be fine like this (e.g. occassional scratching noises are okay, fans aren't)

Obviously without having started coding that yet, I haven't thought it all the way through, but I think that'll work. Feel free to try hacking that idea into the engine and object definition file if you want though, I'm still focusing on objects in the editor for now.

Actually, what I may do tonight is write some documentation. We need at least something, and I can put all of this in there too (and think about it in more detail!). This'll help Grisu and others understand the map, etc, and possibly b able to help out easier.

Good ideas there Mark!

I have stopped work on the editor, so you can change the objects issues as needed. It's nearly impossible to work at the same file at the same time, cause one can't "track" all changes made... :/

Just please post new files with rough named changes here, so we all have the same "state" of code.

Actually, I have some object changes pending (minor ones thus far I'm afraid), but they're generally quite standalone. So long as we don't both hit the same areas of code (i.e. you avoid objects, I only touch objects) we should be okay.

I've found it a lot easier to integrate and spot changes since I discovered a merge tool (*filesComparer*) it's been a lot easier to merge changes in. You might want to take a look. The trick is to keep a replica of the code that you started working from in one directory, your modified code in another, and then when you come to merge changes in, download the latest code. Then you compare yours to the latest and merge your new stuff in. If you get confused as to what you have added / has been added by others, the base from which you worked is then useful to clarify.

I'll definitely post up my changes tonight, plus make a start on some docs.

I'm working on gfx at the moment more than anything, I need a break from the coding for a bit so this is light relief! The good thing about doing gfx is that I keep expanding the map to use the new graphics, although we're going to dump the test level it'll be good to have a single level with pretty much every object in!

On the editor front we really need the special item in as it makes doing interesting stuff (and basic stuff like spawning aliens) tricky.

Mark, when is tonight? ;)

Tonight. :P

Sorry about that. I have made a start on documentation but there's just soooo much! I will post up what I've got by about 1800 GMT. As my parents are visiting this weekend I won't have much of a chance to do anything else until Sunday night, but I'll try to do this!

As for editor changes, forge ahead yourself, I'll patch my stuff in after. So long as you steer clear of stuff relating to objects we should be fine.

Here you go, a start at some documentation. Rob, if you get a chance and fancy it feel free to add to this, tidy up some of my attempting documentation. I'm not going to have a chance to do any more on docs over the next four to five days - what little I do have I want to focus on objects stuff.

*Brief Docs*

And yes, I know I'm one hour late. ;-P

Rob, could you upload your code changes done to editor and engine?

Code and GFX zips updated.

Grisu, I've not put your latest map editor up as I don't like uploading stuff that isn't working 100%

Rob: http://legion.gibbering.net/grisu/rob.zip

I fixed the bug I had earlier. Only had a number typo error.... XD

All should be 100% safe now! So you can include it! :)

P.S.: As always: Take out the Grisu txt debug line... missed to delete that.

Rob: http://legion.gibbering.net/grisu/menu.zip

I changed the main logo, fonts and some other bits.
Think this version looks better than before?

GFX and CODE zips updated.

Grisu, I like your changes with the exception of the new title graphic. I've included both the old and new for people to make up their minds. When I grabbed the inital image I actually toned down the colour to make it look less colour pallete like. Anyway, that aside, all the other changes are in.

I see dead people...



Just drawn a couple of bodies.

They look quite... dead... :D
Sadly Art always has been my worst subject at school days.

Do you think we can make use of this one?


It would still need some border tiles around it...

For the gfxs: I have a huge idea, but its quite some work.
It would be really nice if one could see the current weapon a player is using. Means a flame thrower looks like a flamethrower from above even without firing it!

Is this possilble or too much work?!?

This has been discussed before, quite frankly I think the work involved would outweigh the benefit. It could be done in a quick and dirty way, this would be pretty easy, but would look rubbish, so a lot of time and effort would have to be put into it to make it look better that it currently does. Maybe something to put on the "nice to have" list, but hardly a priority.

Something else... I've had a go at death animations and they look good, done 8 frames that look convincing. The problem... there's still 16 rotations so it's a massive file again, what I propose is that when you die it snaps to one of 4 directions to do the death sequence, this way it'll be close enough, if we don't we're going to be loading another 512k of graphics per character just so they can die... seems a little excessive to me.

Well, personally I don't care for Vmem usage, as we should program AB for modern hardware. But you decide on that. :)

Currently I'm thinking of the best way for adding a preview window to the load room file list...

Well there was another reason for the only 4 directions of death... it only fits in a 64x64 on the 45 deg angles... Here's a quick preview, still not done blood splat decals yet so it looks a bit clean... but fear not... gore will be added!



And I see more dead people...



Looks awesome Rob!

For the editor there should be an object tool as well.
Means you don't have to select tile by tile for construction. Some what like "Select bed" -> "Determine Dir" -> place on map within a mouseclick...
This would speed up level construction, my guess.

Again, we've talked about a 'shapes tool' I added a little copy and paste option just before you joined in. Press tab to start a copy block and tab again to finish the block, then q to paste... the only thing is you can't save prefabs yet.

I've added an extra little bit to it that only copied visible layers too so you can draw a bed, hide the background layers, unhide the collision and copy, then when you paste it will paste all the layers you had visible when you did the copy.

It could be with being tarted up a bit so you can drag areas (like the rooms) but I just did a quick and dirty solution.

On the death animation, how about have the player stagger backwards a bit to face the appropriate direction(s) before kicking in with the death animation?

Player/Weapon gfx are on the todo list above, but as Rob says not really what we need to focus, and probably too fiddly to be worthwhile.

As for objects, when you are editing the object layer, you can place any of the default objects on the map as per tile placement. For level specific, customised objects, a further icon will (once I've posted it up) allow you to place new objects, which you will then customise by right clicking. Hopefully will get a chance to do something this evening (parents have just left, and daughter is asleep).

I look forward to getting the special object working so I can set up spawn points for all the aliens, I've got 2 more waiting in the wings too.

As for the dying I thought just make them spin on the spot to get to the correct direction, I don't think anyone will really notice, especailly in one player mode.

I think we need to add an extra flag to the player type too as a disable controls flag, this way we can get the player to do set pieces (like dying or level start stuff) without worrying about user input and still having all the other stuff like collision working.

I think we're about ready for a new thread, I just want to wait until we've got something significant to start the new thread with. Everything so far has been pretty cosmetic.

Just so you know I've added in the extra flags I was talking about, you can now disable drawing and disable controls for any given player, this is kinda handy if you want to flash the graphic or whatever...

Anyway... I've updated the death aninmation so it looks fine, it's 16 frames and only pointing in one direction. When you die the player spins to the correct orientation... looks fine, so that'll do.

Just got to update the particles system to deal with particles staying forever on the last frame.

Once I've got this lot in I'll update the zips and start a new thread.

Rob, in the code.zip, there are two copies of the editor. editor.bb and editor4.bb.

Which one should we be using? editor4 seems to work best...

I was merging my code in last night and couldn't work out which one to go with.

Editor4 is the newest one... sorry... I was meaning to rename it and delete the old editor... bad housekeeping :(

Now I've killed Bunker, I'm killing Binky now... shame, she's such a nice girl!

I've been playing this for quite a length and while.
And all I can say is, Well Done on A truely terrific and wonderful remake and game!

Cheers!
Great Stuff :)

Editor4 is the newest one

Thought so!

One thing that I'd really like fixed to make the object stuff work well is enabling double click and a graphical means of exiting the ListDlg function. Maybe an Ok and Cancel button at the bottom of it, and writing some double click code. I'd do it myself, but would rather focus on just getting the object stuff working rather than niceties like this...

Great Stuff :)

Thanks!

Time for a new thead this one is way too long now!!

http://www.blitzbasic.com/Community/posts.php?topic=40469