Apr 26, 2015, 06:05 AM | |
I'm trying to get this featured, and I'm not good at making multiplayer levels, so I need you people to give me advice. I'll be glad to mention all of you in the credits for your help. Here's the link with the file |
Apr 26, 2015, 07:58 AM | ||
Quote:
My main issues, is that there is no flow at all (full of places to bump into and many pinpoint areas) and it's full of huge deadends. I really don't get the pole sticking out of the ground. This level could really do with some one-ways and springs (especially at the flowers and areas sticking out from above), and a more simple layout. I'm not a fan of the X-keep blue spring either, as if you're trying to go up from the right, it's fairly easy to end up bumping into the ceiling. Also, this level is virtually unplayable to move around as Lori and hugely Spaz biased. It also seems like you don't know about RF climb. That allows you to access the RF and seek pu area from below. I actually don't mind RF climb areas, though if you can only access them as Spaz... bleh. I'm also not a fan of seek pu secrets, as pretty much anyone who knows the level will win automatically. The seek and bouncer PU and the area topmost the RF PU and that area below the thin platform, also looks pretty campy. I usually avoid making long cramped horizontal areas, as they are too safe or risky. There is no in-between for them because you either can't dodge what will come at you, and it protects against most incoming projectiles. Also, ice in levels that contain pits is good. The best way to make players go to the pit area is to put the most rewarding pickups there. I apply the risk-reward theory to my levels. The risker the area, the greater the reward, and vice versa. One of your primary goals when making a MP level, is that it should be relatively easy and quick to move around, with each path having a purpose. Were concentrating on killing players and escaping, not fighting with the layout. It's okay to have some open areas. To be honest, I think the layout should be started over. There's also a big reason good MP levels don't contain hurt areas. It's that they can be used counter-intuitively to your advantage. Lets say you have strong projectiles coming towards to hit you, but you hop on the spikes instead because they do less damage. It's also an aspect of fighting with the level rather than players themselves. I assume that maybe this level is meant to have more springs and some one-ways, but come on, they don't take long to add.
__________________
|
Apr 27, 2015, 01:29 AM | |
I re-uploaded the file
I followed your advice as best as I could. Am I still missing something? Also, I couldn't find a workaround for the carrotus pole I use as a timed door, as collisions with objects are ignored in multiplayer mode. Note for everyone: Remember to suggest me new ways to make the level better. I'm trying to get it featured. Also feel free to take it in your hands and edit it, and then re-upload it in this thread. Don't upload it in j2o downloads, though. It's my level after all ... Last edited by DennisKainz; Apr 27, 2015 at 01:32 PM. |
Aug 31, 2015, 04:16 AM | |
So hey, how about that grass I was trying to draw about a year ago?
Redid the dirt a while back, and had another go at the grass while I was without internet the other night. As a bonus, any lower grass tile will work with any upper grass tile. A fair bit happier with it than with what I had before, which, for reference, looked like this: I've spent more of my tileset-making time (which admittedly isn't much in the first place) fiddling with the base tiles rather than expanding upon it, though sooner or later I should have a go at padding things out with some more useful tiles so that I can get something I can release.
__________________
Define 'normal'. |
Aug 31, 2015, 04:51 AM | |
The original tiles didn't catch my attention at all but now it definitely looks like something I'd use. It's a huge improvement.
__________________
I am an official JJ2+ programmer and this has been an official JJ2+ statement. |
Aug 31, 2015, 05:45 AM | |
Thanks, glad to hear it. Been putting a lot more effort into learning to actually draw properly, rather than just relying on tricks and cheats to get it to look ok. It's a little slow but I think I've been making some progress.
__________________
Define 'normal'. |
Aug 31, 2015, 07:37 AM | |
But I made a thread for projects asides from level WIPs...
http://www.jazz2online.com/jcf/showthread.php?t=19861 Anyway, a nice improvement.
__________________
|
Aug 31, 2015, 10:56 PM | |
very pretty! but do the tiles look good even without the layer 3 bits? if I were to use this in a level, I'd likely want to do parts with normal grass, and some with beaten grass
__________________
"So unless I overwrote my heart with yours, I think not. But I might have." - Violet CLM Two Games Joined releases: Control / Splinter (twin singles) || Ballistic Bunny (EP) || Beyond (maxi-single) || Beyond: Remixed (remix EP) || Inner Monsters OST (mini-album) || Shadows (album) |
Sep 1, 2015, 04:29 AM | |
No, not at all. The layer 4 bits are just the layer 3 with a bit of "background" grass to make it still look ok if you can't be bothered doing layer 3 stuff over the whole level. I could potentially change that, I suppose, or perhaps add a variant of upper grass tiles that's more beaten down.
__________________
Define 'normal'. |
Sep 1, 2015, 12:25 PM | |
I suggest you do this.
|
Sep 2, 2015, 12:43 AM | |
By request, updating an old CTF level.
__________________
Join clan [GPW]'s discord! https://discord.gg/ktCcYnv S.H.A.D.O.W.: (aka Ins0mnia) Synthetic Hydraulic Android Designed for Observation and Warfare Mystic Legends http://www.mysticlegends.org Follow me on twitter: @Ins0mnia Follow us on twitter: @Mystic_Legends |
Sep 2, 2015, 10:45 AM | |
I started working on this CTF water level around one month ago but gave up due to lack of interest. Should I keep working on it? It is not done but I feel like the entire design of the map is just not good. What do you guys think?
__________________
"Floppy ears and a big butt?" - Slaz |
Sep 2, 2015, 01:27 PM | ||
Quote:
Anyway, it's very corridory and horizontal. And it looks like the 1 tile passages above the middle would be campy. Whatever is in those cramped looking deadends that are above the tight bottom passage, looks potentially campy as well. Same with those 1 tile passages that lead to the top. Making an interesting layout is mixing horizontal and vertical spaces and utlising different ways to reach areas (I don't mean as many alternate paths as possible, I simply mean not relying on one method of platforming to reach up areas). Varying the size of spaces allows for more varied gameplay too, and have no need to be parallel, (excessive parallel passages results in a corridory layout which is bland if you ask me). And be sparse on cramped areas, because people will camp in them, and/or it'll get annoying having to get hit by everything. Though 1 tile vertical passages are fine, providing the area above isn't hard to counter. I'm also not a fan of entirely closing up the top area unless it's inside something man made or a cave. Though to be honest, I don't recommend making MP levels if you haven't played the gamemode much, if not at all. When you play online (the main MP gamemodes such as battle and CTF) for a good while, you get a much better idea of what works well and what doesn't.
__________________
|
Sep 2, 2015, 02:27 PM | |||
Quote:
I tried to make it more vertical, it was in the original plan. I was trying to remake TF2's 2fort map in 2D but during the progress I kind of forgot what it was supposed to look like in my mind. Didn't really turn out like that map at all. Where the 1 tile passages are, there are the flags. I know, it is a terrible position for a flag but gave up before finding a better one. I will try to make passages wider the next time, I guess. I really do apreciate this tip. I am a little bad when it comes to level design (I'm a little bad when it comes to everything actually) but I'd really like to improve. I will keep that in mind, thanks I guess when I will get to finish the map (maybe) I will open up the top area. *rabbit made I guess that's my biggest downside. I don't play MP much because I'm just bad at it and I don't find it very entertaining either (I do like the relaxers and streetfighters though). I will try to get myself playing more though, maybe it will seem easier and funner when I get the hang of it. Quote:
That's sweet. I hope you will write it someday, it would be a very useful thing.
__________________
"Floppy ears and a big butt?" - Slaz |
Sep 2, 2015, 03:13 PM | |
To be pedantic: Making an area wider means making it more horizontal. That's not what the map needs lol.
The best CTF base placements are defendable, but also attackable. And not too easy to rush. So I think the best place would be at the middle, placed amongst the corner further from the bottom vine(?).
__________________
|
Sep 3, 2015, 01:46 AM | ||
Quote:
__________________
"Floppy ears and a big butt?" - Slaz |
Sep 3, 2015, 11:03 AM | |
Copy the following code, paste it into a text editor, save as SEscreenshot.mut, enable it in JJ2+ by typing "
/mutators sescreenshot on ", cycle to the level you want to take a screenshot of, type "!screenshot ", wait between several seconds to several minutes depending on level size (yes, it can take several minutes, and the game will act as if frozen for that time, don't attempt to interact with it or Windows will assume it stopped responding), a file named "SEscreenshot.ppm.asdat" will appear in your JJ2 directory, remove the ".asdat" extension, use an image editor to convert the resulting PPM to a PNG, perhaps shrink the image if its file size is still too big for your needs.Optionally: instead of " !screenshot " you can type "!screenshot file_name " or "!screenshot "file name" " (replacing file_name with a selected string of text, the latter syntax allowing whitespace) to save a picture with a custom file name.Code:
#pragma name "Full Level Screenshot" jjPALCOLOR getColor(jjPALCOLOR dest, int index, SPRITE::Mode mode, int param) { jjPALCOLOR source = jjPalette.color[index]; switch (mode) { case SPRITE::BRIGHTNESS: return param < 128 ? jjPALCOLOR(dest.red * param >> 7, dest.green * param >> 7, dest.blue * param >> 7) : jjPALCOLOR(~(~dest.red * param >> 7), ~(~dest.green * param >> 7), ~(~dest.blue * param >> 7)); case SPRITE::FROZEN: { jjPALCOLOR color(dest.red + source.red * 3 >> 2, dest.green + source.green * 3 >> 2, dest.blue + source.blue * 3 >> 2); int light = color.getLight(); return jjPALCOLOR(light >> 3, light * 5 >> 3, light); } case SPRITE::GEM: { const array<int> hue = {245, 106, 136, 201}; jjPALCOLOR color; color.setHSL(hue[param & 3], 255, index << 1); return jjPALCOLOR(dest.red + color.red * 3 >> 2, dest.green + color.green * 3 >> 2, dest.blue + color.blue * 3 >> 2); } case SPRITE::INVISIBLE: return dest; case SPRITE::PALSHIFT: return jjPalette.color[(index + param) & 255]; case SPRITE::PLAYER: { jjPLAYER@ player = jjPlayers[param]; CHAR::Char chara = player.charCurr; bool inRange0 = index >= (jjIsTSF && chara == CHAR::LORI ? 24 : 16) && index < 48; bool inRange1 = index >= 88 && index < 96 && jjIsTSF && chara == CHAR::LORI; bool inRange2 = index >= 80 && index < 88 && (chara == CHAR::BIRD || chara == CHAR::BIRD2 || chara == CHAR::FROG); bool inRange3 = index >= 59 && index < 64 && chara != CHAR::BIRD && chara != CHAR::BIRD2; if (inRange0 || inRange1 || inRange2 || inRange3) { array<uint> fur(4); for (int i = 0; i < 4; i++) { fur[i] = player.fur >> (i << 3); } if (chara == CHAR::BIRD) { for (int i = 0; i < 2; i++) { uint temp = fur[i]; fur[i] = fur[i | 2]; fur[i | 2] = temp; } } if (inRange0) index -= 16; else if (inRange1) index -= 88; else if (inRange2) index -= 80; else if (fur[3] != 40) index -= index < 61 ? 34 : 33; else return source; return jjPalette.color[(fur[index >> 3] + (index & 7)) & 255]; } } return source; case SPRITE::SINGLECOLOR: return jjPalette.color[param]; case SPRITE::TRANSLUCENT: return jjPALCOLOR(dest.red + source.red >> 1, dest.green + source.green >> 1, dest.blue + source.blue >> 1); } return source; } void drawLayers(array<array<jjPALCOLOR>>& image, const array<int> &in layers) { int width = image.isEmpty() ? 0 : image[0].length(), height = image.length(); int layerCount = layers.length(); array<jjPALCOLOR> translucentPixels; for (int i = 0, j = 0; j < height; (i++) == (j += 32)) { for (int k = 0, l = 0; l < width; (k++) == (l += 32)) { array<int> tiles(layerCount, -1); for (int m = 0; m < 32; m++) { array<jjPALCOLOR>@ row = image[j | m]; for (int n = 0; n < 32; n++) { int column = l | n; for (int o = 0; o < layerCount; o++) { int tile = tiles[o]; if (tile < 0) { int layer = layers[o]; int layerWidth = jjLayerWidth[layer], layerHeight = jjLayerHeight[layer]; int x = k, y = i; if (x >= layerWidth) { if (jjLayerTileWidth[layer]) x %= layerWidth; else x = -1; } if (y >= layerHeight) { if (jjLayerTileHeight[layer]) y %= layerHeight; else y = -1; } tile = tiles[o] = x >= 0 && y >= 0 ? jjTileGet(layer, x, y) : 0; } int index = jjPIXELMAP(tile)[n, m]; if (index != 0) { jjPALCOLOR color = jjPalette.color[index]; if (tile & TILE::ANIMATED == 0 && jjTileType[tile & TILE::RAWRANGE] == 1) { translucentPixels.insertLast(color); } else { row[column] = color; break; } } } while (!translucentPixels.isEmpty()) { jjPALCOLOR one = translucentPixels[translucentPixels.length() - 1], two = row[column]; row[column] = jjPALCOLOR(one.red + two.red >> 1, one.green + two.green >> 1, one.blue + two.blue >> 1); translucentPixels.removeLast(); } } } } } } void drawFrame(array<array<jjPALCOLOR>>& image, jjANIMFRAME@ frame, int x, int y, int d, SPRITE::Mode mode, int param) { const jjPIXELMAP source(frame); int width = frame.width, height = frame.height; int xMax = image.isEmpty() ? 0 : image[0].length(), yMax = image.length(); bool hFlip = d < 0, vFlip = (d & 0xC0 != 0) && (~d & 0xC0 != 0); x += hFlip ? 1 - (width + frame.hotSpotX) : frame.hotSpotX; y += vFlip ? 1 - (height + frame.hotSpotY) : frame.hotSpotY; int xDir = hFlip ? -1 : 1; int yDir = vFlip ? -1 : 1; int xStart = hFlip ? width - 1 : 0; int yStart = vFlip ? height - 1 : 0; for (int i = 0, j = y, k = yStart; i < height; (i++) ^ (j++) ^ (k += yDir)) { if (j >= 0 && j < yMax) { array<jjPALCOLOR>@ row = image[j]; for (int l = 0, m = x, n = xStart; l < width; (l++) ^ (m++) ^ (n += xDir)) { if (m >= 0 && m < xMax) { int index = source[n, k]; if (index != 0) row[m] = getColor(row[m], index, mode, param); } } } } } void takeScreenshot(const string &in filename) { array<int> fgLayers, bgLayers; for (int i = 1; i < 8; i++) { if ( jjLayerHasTiles[i] && jjLayerXSpeed[i] == 1.f && jjLayerYSpeed[i] == 1.f && jjLayerXAutoSpeed[i] == 0.f && jjLayerYAutoSpeed[i] == 0.f && jjLayerXOffset[i] == 0.f && jjLayerYOffset[i] == 0.f ) (i < 4 ? fgLayers : bgLayers).insertLast(i); } bgLayers.insertLast(8); int width = jjLayerWidth[4] << 5, height = jjLayerHeight[4] << 5; array<array<jjPALCOLOR>> image(height, array<jjPALCOLOR>(width)); drawLayers(image, bgLayers); for (int i = 1; i < jjObjectCount; i++) { const jjOBJ@ obj = jjObjects[i]; if (obj.isActive && obj.curFrame != 0 && obj.eventID != OBJECT::STOMPSCENERY && obj.eventID != OBJECT::COLLAPSESCENERY && obj.eventID != OBJECT::DESTRUCTSCENERY && obj.eventID != OBJECT::DESTRUCTSCENERYBOMB ) { if (obj.eventID == OBJECT::CTFBASE) { int animSet = jjAnimSets[ANIM::FLAG], x = int(obj.xOrg), y = int(obj.yOrg), d = obj.var[2] != 0 ? 1 : -1, t = jjGameTicks / 6; const jjANIMATION@ anim; @anim = jjAnimations[animSet + 1]; drawFrame(image, jjAnimFrames[anim + obj.var[1]], x + 5 * d, y + 17, d, SPRITE::NORMAL, 0); @anim = jjAnimations[animSet + 2]; drawFrame(image, jjAnimFrames[anim + t % anim.frameCount], x + 23 * d, y - 36, d, SPRITE::NORMAL, 0); if (obj.var[4] == 0) { @anim = jjAnimations[animSet + 5]; drawFrame(image, jjAnimFrames[anim + t % anim.frameCount], x - 64 * d, y - 4, -d, SPRITE::NORMAL, 0); } else { @anim = jjAnimations[animSet + 6]; drawFrame(image, jjAnimFrames[anim + obj.counter / 4 % anim.frameCount], x - 64 * d, y - 4, -d, SPRITE::NORMAL, 0); } } int pickupAnim = obj.curAnim - jjAnimSets[ANIM::PICKUPS]; jjANIMFRAME@ frame = jjAnimFrames[obj.curFrame]; SPRITE::Mode mode; int param = 0; if (obj.freeze != 0) { mode = SPRITE::FROZEN; } else if (obj.justHit != 0) { mode = SPRITE::SINGLECOLOR; param = 15; } else if (pickupAnim == 22 || pickupAnim == 34 || pickupAnim == 35) { mode = SPRITE::GEM; param = obj.var[0] - 1; } else if (frame.transparent) { mode = SPRITE::TRANSLUCENT; } else { mode = SPRITE::NORMAL; } drawFrame(image, frame, int(obj.xPos), int(obj.yPos), obj.direction, mode, param); } } for (int i = 0; i < 32; i++) { const jjPLAYER@ player = jjPlayers[i]; if (player.isInGame && !player.invisibility) drawFrame(image, jjAnimFrames[player.curFrame], int(player.xPos), int(player.yPos), player.direction ^ (player.antiGrav ? SPRITE::FLIPV : SPRITE::FLIPNONE), player.frozen == 0 ? player.spriteMode : SPRITE::FROZEN, player.spriteParam); } drawLayers(image, fgLayers); jjSTREAM file; string header = "P6 " + width + ' ' + height + " 255\n"; int headerLength = header.length(); for (int i = 0; i < headerLength; i++) { file.push(header[i]); } for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) { jjPALCOLOR color = image[i][j]; file.push(color.red); file.push(color.green); file.push(color.blue); } } file.save(filename); } bool onLocalChat(string &in text, CHAT::Type type) { array<string> results; if (type == CHAT::NORMAL && jjRegexMatch(text, """!screenshot(?:\s+([^\s"]+|"([^"]+)"))?\s*""", results, true)) { string filename; if (results[1].isEmpty()) filename = "SEscreenshot"; else if (results[2].isEmpty()) filename = results[1]; else filename = results[2]; takeScreenshot(filename + ".ppm.asdat"); return true; } return false; }
__________________
I am an official JJ2+ programmer and this has been an official JJ2+ statement. |
Dec 1, 2015, 03:43 PM | |
Getting back to my roots or something with a good old-fashioned test level. Well, except for the scripting. |
Dec 9, 2015, 05:53 AM | |
This is a very hard level that I'm working on, called "The Impossible One". You have 1 only heart, can't run or use special moves, and you must save on ammunitions for when you'll need them. I've tested most of the level by myself, and I'm pretty sure it CAN be completed. I need you people to help me with a few things: - Make sure there are exactly 66 enemies, and that they can be ALL defeated even in Turbo mode (every single shot must be done right) - Make sure all puzzles can actually be solved - Help me fix the bug where the player is killed by the RF blast (When you fall from too high, you die, but a RF blast from above also crushes you to the ground) - Help me fix the annoying stomping sound on slippery slopes - Help me fix the deactivation bug where some enemies do not reappear if you walk too far and then return HERE'S THE FILE (hopefully) The part around the triggered pool is a Reworder thing that I'll compile when the level is done. Thanks to Violet for explaining me the trick to rescale backgrounds. Also, I restarted working on the level "Beneath the World we know". HERE'S THE LINK Last edited by DennisKainz; Dec 23, 2015 at 07:33 AM. |
Jan 2, 2016, 01:22 AM | |
Currently working on a new test. I had planned to finish it before the end of 2015, but that was before I discovered how difficult the selected tileset is. Also, I had other things on my mind, so working on this test wasn't always guaranteed. I use the Blizzard tileset (night version), which brings with it a lot of opportunities. All my work so far has been put into animating tiles, creating an environment, discovering how everything works so as to prevent tilebugs, thinking of a 'story' I could implement, etc.
I have yet to start working on the first level. What I'll try to do is to make sure it's not a conventional test which just goes from level one to level last and that's it. No, there should be something more to it than that. Without knowledge of AngelScript and all that kind of fancy stuff, my powers may be limited, but I'll try to make the best out of it nontheless. Heh, with all that written here, I wonder what I'm going to write in the description as soon as I upload this. Maybe the same story, but extended a little ^^. |
Jun 8, 2016, 10:11 PM | |
Very early stages in terms of graphics and layout, but there's like 300kb of supplementary files already...
|
Jul 21, 2016, 07:50 AM | |
Something's brewing in Aesop's book of green hares and tortoises.
Unlike how most of you start, I decided to start with the column order (and not in proper order, as well—I started with Ionic, then made the Corinthian). For now I plan to use a recolored version of Castle as the base, plus custom-made ground tiles, plants from Jungle or another tileset, destructible vases and pottery, fountains, statues and grapevine vines. Probably some red and blue versions of some blocks, for CTF purposes. Also, some custom animated enemies from opengameart.com, but there's quite a lot of work before I even begin thinking about implementing new enemies. **EDIT:** Well, I decided the best fit would be a reworked conversion from JJ1 Stonar. Here are two updated screenshots (I removed the old ones) which show the two palettes in which the tileset will come. Aesopia Day Aesopia Evening Last edited by AvalancheMaster; Jul 23, 2016 at 02:37 PM. |
Jul 30, 2016, 06:20 AM | |
Sorry for double-posting, but since this is a completely different project, I think it's worth a bump.
The Green Knight Rises! (Actually called "Arkham Rabbits") A 1v1 Battle level I'm working on for me and my friend to play. It uses a modified version of blurredd's Windstorm Fortress, so I'll have to wait for an approval on his end to release it publicly. |
Jul 30, 2016, 10:52 AM | |
Genuinely looking forward to get the opportunity to play those levels.
I find your use of tileset merges really inspiring. |
Aug 29, 2016, 06:19 PM | ||
Quote:
Updating my previous screenshot. |
Aug 29, 2016, 06:42 PM | |
Is..that my large heart edit? I don't mind at all though.
__________________
|
Aug 30, 2016, 02:04 AM | |
That looks intriguing! Can't wait to see it in action.
|
Aug 30, 2016, 09:06 PM | |
Trey: I don't believe so? I recall your mentioning such a thing, but I'm pretty sure I made one myself at some point, and the sprite I used for this level has the filename that I would have used. So unless I overwrote my heart with yours, I think not. But I might have.
|
Aug 31, 2016, 06:12 AM | |
sorry for offtopic, but that last part was so poetic I just had to put it in my sig
__________________
"So unless I overwrote my heart with yours, I think not. But I might have." - Violet CLM Two Games Joined releases: Control / Splinter (twin singles) || Ballistic Bunny (EP) || Beyond (maxi-single) || Beyond: Remixed (remix EP) || Inner Monsters OST (mini-album) || Shadows (album) |
«
Previous Thread
|
Next Thread
»
Thread Tools | |
|
|
All times are GMT -8. The time now is 02:46 PM.
Jazz2Online © 1999-INFINITY (Site Credits). Jazz Jackrabbit, Jazz Jackrabbit 2, Jazz Jackrabbit Advance and all related trademarks and media are ™ and © Epic Games. Lori Jackrabbit is © Dean Dodrill. J2O development powered by Loops of Fury and Chemical Beats. Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Original site design by Ovi Demetrian. DrJones is the puppet master. Eat your lima beans, Johnny.