Welcome, Guest. Please login or register.
Did you miss your activation email?

Login with username, password and session length

 
Advanced search

1347615 Posts in 61901 Topics- by 53552 Members - Latest Member: SweetieBun

September 22, 2018, 07:50:38 AM

Need hosting? Check out Digital Ocean
(more details in this thread)
TIGSource ForumsCommunityDevLogsLeilani's Island
Pages: 1 ... 41 42 [43] 44 45
Print
Author Topic: Leilani's Island  (Read 144893 times)
fall_ark
Level 1
*



View Profile
« Reply #840 on: May 31, 2018, 03:01:24 AM »


For Chinese I would indeed have to draw a lot of characters, but since the game is relatively light on text, as long as I only drew the characters that were necessary then I think it would be doable. I expect line breaks would need to be done manually (at least I heard that's the case for Japanese), but other than that my font system should handle it fine.

It's generally a bad idea to try to create Chinese pixel font by oneself, especially since that size (11~12px) is already the minimum needed to make the font readable, so you can't really have a unique style. There are a few free Chinese pixel fonts around and I can send you the one we made ourselves (it's used in The Count Lucanor and in the old pixel-font version of Dead Cells) if needed.

Basic line-breaking simply needs to treat every CJK character (unicode 0x4e00 to 0x9fea) as a space. Some extra work is needed in relation to punctuation marks, but it's not really a big deal.
Logged

Chinese localizer and influencer. Translated Dead Cells, Slay the Spire, The Count Lucanor, and involved in the localization of Reigns, The Curious Expedition, Desktop Dungeons, etc.
Now also coordinating Chinese and global publishing for Indienova and WhisperGames. Send me an email if interested.
DrDerekDoctors
THE ARSEHAMMER
Level 8
******



View Profile WWW
« Reply #841 on: June 01, 2018, 12:11:04 AM »

I like the control over the appearance of the outline that I get when I draw the outline by hand.

Looking at some examples of how to outline the letter C, a shader could choose to:
- Draw the outline on adjacent and diagonally adjacent pixels (second example), this makes edges that should be smooth look way too heavy.
- Draw the outline only on adjacent pixels (third example), this makes the sharp square corners look too rounded.



By hand-drawing the outline myself (fourth example), the curvy bits can look curvy and the sharp corners can look sharp.

Aha! That makes a lot of sense, yuss! Smiley
Logged

Me, David Williamson and Mark Foster do an Indie Games podcast. Give it a listen. And then I'll send you an apology.
http://pigignorant.com/
Louard
Level 2
**


View Profile WWW
« Reply #842 on: June 01, 2018, 10:45:28 AM »

Enjoy your time off, Ishi! You know I'll be checking in regardless... Just in case  Tongue
Logged

-Louard
louardongames.blogspot.com
Josh Bossie
Level 2
**


Fly Safe, Pupper


View Profile WWW
« Reply #843 on: June 02, 2018, 02:55:47 PM »

Really loving the nerdy tech talk in the last page. Wish more of us talked as in depth about these things

Not loving the nightmarish pug which I can no longer unsee
Logged

Ishi
Pixelhead
Level 10
******


coffee&coding


View Profile WWW
« Reply #844 on: July 05, 2018, 11:44:01 AM »

Aloha!

Thanks for your patience while I had my break. I'm now back to work on the game! I've been easing back into development by just doing various quality of life / polish tasks. It's nice to do smaller things to get a feel for the game again, get the game in my head and start thinking about which major area to focus on next.

I'll go over some of the changes I've made in the last week.

Improved Main Menu

The old main menu background (on the left) looked very placeholder. I've improved the foliage and given it some animation which looks way nicer. I also added some animations to Leilani's disembodied hand - I always intended to have her hand punch the buttons when they're selected, so was nice to finally get that in the game.

-->

Credits

I also put a proper credits screen in. It did exist previously but was just some unreadable pink and green text with no backdrop, and no scrolling. Now it can be expanded to eventually fit as many playtesters as I want Smiley



Close Game button

Closing the game in full screen mode was really awkward previously - you had to exit back to the world map, then exit back to the title screen, then press OK on the title screen, then finally from the main menu you could close the game. So I added a button in the pause menu (accessible during gameplay, or on the world map) to instantly quit the game, with a confirmation prompt.



One thing I need to addres here is that, if the player is holding Right when the game is paused, the cursor immediately moves over to the Close Game button. I'll change it so that when pausing the game, directional inputs won't respond until they've been released and then re-pressed. This should make it feel much nicer to pause the game while Leilani is moving.

Checkpoint!



I added a little checkpoint fanfare! This was based on feedback from a previous playtest. It helps to clarify what the checkpoint actually is for new players, and for experienced players I think it looks nice. I like that the game is mostly text-free, but sometimes a word or two of explanation can help.

SDL Upgrade

I upgraded to a newer version of SDL! I've gone from version 2.0.3 to 2.0.8. There are a couple of useful changes for me in the new version.
  • The ability to ignore mouse inputs that focus the window (e.g. clicking on the window to bring it to the front). In Leilani, clicking pauses the game, so it's nice to be able to re-focus the window without pausing.
  • The ability to prevent touch inputs from emulating mouse inputs. In the previous version of SDL, using a touch screen (for example on a laptop) would produce touch inputs, and SDL would also generate mouse inputs. Since I want the menus to respond slightly differently between touch and mouse, this was really awkward, and I had various hacks in place to ignore mouse inputs that looked like they were copies of touch inputs. Now I can just turn this weird feature of SDL off and delete the hacks from my input code. Smiley

I also did a couple of other small bits and bobs. It's been a productive time!

Thanks for reading, please look forward to having more regular updates again Coffee
Logged

JobLeonard
Level 10
*****



View Profile
« Reply #845 on: July 06, 2018, 07:51:56 AM »

It's actually really cool to see how much polish even the little things require
Logged
Permafrost11
Level 0
**


[Sample Text]


View Profile
« Reply #846 on: July 10, 2018, 06:13:28 PM »

This game's art style really reminds me of those early 2010s Nitrome games.
Logged

You should totally check out my game that I revived: https://forums.tigsource.com/index.php?topic=65065.0
Ishi
Pixelhead
Level 10
******


coffee&coding


View Profile WWW
« Reply #847 on: July 14, 2018, 11:07:55 AM »

This week I have mostly been looking at controller rumble! A small note on my todo list - "try implemented rumble again" - ended up filling the entire week.

Controller Rumble

I've had controller rumble support in the game for ages - but it was only for Xbox controllers, using the XInput API. Then at some point I stopped using the XInput API altogether (SDL's input system provides the same functionality via its Controller feature). I had partially implemented rumble using SDL but never actually got it working.

After fixing my past mistake I then fleshed out my rumble code in various ways. Below I'll discuss some of it.

Actually enabling Rumble

Firstly the important thing bit of code which actually made the rumble start working:

Code:
SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMECONTROLLER)

Became:

Code:
SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMECONTROLLER | SDL_INIT_HAPTIC)

I needed to tell SDL to initialise the haptic system. I had totally missed this previously Grin Unfortunately when trying to use the haptic system without initialising it first, the errors returned from the SDL API are along the lines of "this controller doesn't support haptics" rather than "you didn't initialise the system yet". So it's worth being extra careful when following the documentation about how to use the system, so you don't miss any steps.

SDL Haptics Overview

Once you have an SDL joystick or controller, you can open the haptic system on it. After opening the system, you then have a choice of either initialising the simple rumble system, or creating a new haptic effect.

The simple rumble system is a super-basic wrapper which you give a 0-1 value, and it'll make the device vibrate in some way. Presumably using this is a good way of ensuring basic support of any device with some kind of rumble support. I only have Xbox controllers to test with. The simple rumble system makes both of the controller's motors vibrate at the same strength.

Using a haptic effect rather than the simple rumble gives you more control over specific features of the device. There are various types of haptic effect available, which you can query whether the device supports before using. I'm guessing most of them are related to things like force feedback steering wheels. The one I care about is SDL_HAPTIC_LEFTRIGHT - this allows you to control the two motors in the Xbox controller separately.

In the Xbox controller one motor is a high frequency rumble (so more like a fine buzz) and the other motor is a low frequency rumble (so more like a heavy shake). Being able to control these separately is really nice, as it offers more nuance into the kind of feedback you give through the controller.

SDL Haptics Code

I have a rumble manager. The game tells the manager when to start a rumble effect, and what the effect is like, etc. I won't go into too much detail right now. But each frame this rumble manager combines all the active rumble effects into two values - the strength of rumble for the light motor, and the strength of rumble for the heavy motor. This data then needs to be applied to the player's controller.

The data looks like this.

Code:
struct sRumbleState
{
sRumbleState()
: LightRumble(0.0f)
, HeavyRumble(0.0f)
{
}

float ToSingleFloat() const
{
return Toolbox::highest(LightRumble * 0.33f, HeavyRumble);
}

float LightRumble;
float HeavyRumble;
};

The ToSingleFloat() function provides a way to get a single float value rather than separate LightRumble and HeavyRumble values. This single float value is used if the controller only supports the simple rumble system rather than the SDL_HAPTIC_LEFTRIGHT effect.

But before we can apply these values to the device we need to open the SDL haptic system on it.

Here's a simplified version of my function to open the haptics on the controller.

Code:
void cDeviceRumbleHelper::Open(SDL_Joystick *pJoystick)
{
m_pHaptic = SDL_HapticOpenFromJoystick(m_pJoystick);
if (m_pHaptic)
{
if ((SDL_HapticQuery(m_pHaptic) & SDL_HAPTIC_LEFTRIGHT) != 0)
{
// Controller supports SDL_HAPTIC_LEFTRIGHT rumble. Try to initialise it
SDL_memset(&m_HapticEffectParams, 0, sizeof(SDL_HapticEffect));
m_HapticEffectParams.type = SDL_HAPTIC_LEFTRIGHT;
m_HapticEffectParams.leftright.length = SDL_HAPTIC_INFINITY;
m_HapticEffectParams.leftright.large_magnitude = (Uint16)(0.0f * LEFTRIGHT_MAX_VALUE);
m_HapticEffectParams.leftright.small_magnitude = (Uint16)(0.0f * LEFTRIGHT_MAX_VALUE);

m_HapticEffectID = SDL_HapticNewEffect(m_pHaptic, &m_HapticEffectParams);
}

if (m_HapticEffectID < 0)
{
// Initialise simple rumble as a fallback
SDL_HapticRumbleInit(m_pHaptic);
}
}
}

It's easy to query whether the device supports SDL_HAPTIC_LEFTRIGHT, and then create the haptic effect. If SDL_HAPTIC_LEFTRIGHT is not supported, it falls back to initialising the simple rumble system.

And then each frame, I call this function to send the rumble to the device.

Code:
void cDeviceRumbleHelper::SetRumble(const sRumbleState &rumbleState)
{
if (m_pHaptic)
{
if (m_HapticEffectID >= 0)
{
// Use the leftright rumble effect to control both motors
if (rumbleState.HeavyRumble > 0.0f || rumbleState.LightRumble > 0.0f)
{
// Update the effect with new values
m_HapticEffectParams.leftright.large_magnitude = (Uint16)(rumbleState.HeavyRumble * LEFTRIGHT_MAX_VALUE);
m_HapticEffectParams.leftright.small_magnitude = (Uint16)(rumbleState.LightRumble * LEFTRIGHT_MAX_VALUE);
SDL_HapticUpdateEffect(m_pHaptic, m_HapticEffectID, &m_HapticEffectParams);

// Play the effect if it's not running
if (!m_HapticEffectRunning)
{
if (SDL_HapticRunEffect(m_pHaptic, m_HapticEffectID, 1) == 0)
{
m_HapticEffectRunning = true;
}
}
}
else
{
// Stop the effect if it's running
if (m_HapticEffectRunning)
{
SDL_HapticStopEffect(m_pHaptic, m_HapticEffectID);
m_HapticEffectRunning = false;
}
}
}
else
{
// Use simple rumble
float strength = rumbleState.ToSingleFloat();
if(strength > 0.0f)
{
SDL_HapticRumblePlay(m_pHaptic, strength, SDL_HAPTIC_INFINITY);
}
else
{
SDL_HapticRumbleStop(m_pHaptic);
}
}
}
}

This function has to be called every frame. I use SDL_HAPTIC_INFINITY to tell the effect/simple rumble to play forever, so the controller will only stop rumbling when SDL_HapticStopEffect / SDL_HapticRumbleStop is called.

Full code for these functions can be found here for those interested:
RumbleState.h
DeviceRumbleHelper.h
DeviceRumbleHelper.cpp

I feel it was definitely worth figuring this stuff out, I love rumble when it's done properly! Especially because Xbox controllers are so common on PC, it was a must-implement feature for me to make full use of the high/low frequency rumble motors.

Xbox One Controller

Speaking of which, this week while working on the rumble system I was able to briefly try out a friend's Xbox One controller. I had never been interested in buying one of these before, I already have three Xbox 360 controllers and at least two other USB PC controllers.

What I was blown away by was how much better the rumble is on the Xbox One controller. It has the same basic setup as the 360 controller - a high and low frequency motor - but they are way more responsive, especially when doing gentle rumble. One of my rumble effects runs the high frequency motor at only 5% strength for 0.075 seconds, and this consistently produces a nice gentle "tap" sort of feeling. If I run the same effect on the 360 controller, basically nothing happens.

So, I bought an Xbox One controller. Smiley I'll be trying to make full use of this fine detail rumble to enhance the feedback of what's going on in the game.

A sidenote, the Xbox One controller also has a thing called Impulse Triggers where the triggers themselves vibrate. But from what I've read online, this can only be used on the Xbox One itself, or through Windows Store apps, so I'm just ignoring this feature.

Rumble test mode

Finally, since this post has been gif-free, here's the rumble test mode that I put together to make my testing easier.



It allows me to cycle through all the rumble effects in the game and trigger them. The bars show the current vibration strength of the light (left) and heavy (right) motors.

I hope this has been interesting / useful to you! Thanks for reading Smiley
Logged

Aw0
Level 0
**


ㅇㅅㅇ


View Profile WWW
« Reply #848 on: July 14, 2018, 09:30:23 PM »

Hey there! I've watched this project from afar for a about 2 years but now I finally have an account here lol
I absolutely love what you have going!  Kiss Truly inspiring! Can't wait to try it out someday.
Logged

pwei
Level 0
**


View Profile
« Reply #849 on: July 15, 2018, 11:34:35 AM »

I'm not a fan of this art style / theme -- but I have to say after watching the gameplay videos and reading through this devlog I am impressed. Seeing how thoughtfully mechanics and details are being designed makes me eager to give this game a try when it's released. Keep up the good work.
Logged
Ishi
Pixelhead
Level 10
******


coffee&coding


View Profile WWW
« Reply #850 on: July 20, 2018, 12:28:06 PM »

I'm not a fan of this art style / theme -- but I have to say after watching the gameplay videos and reading through this devlog I am impressed. Seeing how thoughtfully mechanics and details are being designed makes me eager to give this game a try when it's released. Keep up the good work.

Thanks for the nice words, happy it can be of interest even if the game's not quite to your tastes Smiley

Hey there! I've watched this project from afar for a about 2 years but now I finally have an account here lol
I absolutely love what you have going!  Kiss Truly inspiring! Can't wait to try it out someday.

Thanks!
Logged

Ishi
Pixelhead
Level 10
******


coffee&coding


View Profile WWW
« Reply #851 on: July 20, 2018, 01:28:22 PM »

It's devlog time!

This week I've been working on planning out the scope of the game, in terms of the number of levels. It's getting so serious I even made a spreadsheet. I started by going through all of the levels (and parts of levels) that I currently have, making notes on how finished they are, what small or large tweaks they need, and putting them in a rough order. Then I began to add levels that I don't have to the list, to get an idea of the amount of work remaining. It's nice to have a more concrete idea of where I'm actually at.

I don't have anything to show you from this but it feels like nice progress for me. I'm going to continue working on this sheet some more, there are some existing levels that I still need to review and make notes on, and plenty of spaces to fill with ideas for potential levels and the gimmicks/mechanics they could feature.

Bug-fix process

One thing that happened this week was that I found a fairly obscure bug. I thought it might be interesting to explain the process I took to fix it.

1. Encounter the bug

While playing through the game's first level, I noticed that Leilani jumped higher than she normally can. Her jump is only 3 tiles high, but I was able to clear a 4-tile-high wall quite easily.

Fortunately I have a gameplay-recording feature in place. The game already saved out a recording of my inputs that resulted in the bug. By dropping the recording file into the game, I can replicate the bug.



When Leilani jumps up onto the blue platform - she's not meant to be able to jump that high.

2. Try to reproduce it

The first thing I did was to pick up the controller myself and start trying to recreate the jump. I thought that maybe bouncing on the enemy beforehand was important - jumping off the top of enemies gives Leilani a higher jump than normal, and maybe that higher jump style was being carried over to the next jump after hitting the enemy? But I wasn't able to recreate it.

3. Analyse the recorded gameplay

Luckily I could fall back on using the recording to reproduce the bug, a luxury that most games don't have. This has cemented my opinion that a gameplay recording feature is worth the time taken to implement wherever possible!

I added some debug info about Leilani's jump state on the screen. Then played the recording back and took a video of it, so I can step through the video and look at the values on each frame. I find this is a really useful and visual way to debug things, rather than printing tons of info out to the output window and then trying to make sense of it later.

These are the values on the frame when Leilani begins the buggy jump:



I then recorded myself doing a normal jump to compare:



It turns out the cause of the higher jump is obvious. Entities in the game each have a Gravity Multiplier value, which affects how strongly they accelerate due to gravity. I change this value at various times, because I'm happy to just mess with the rules of physics to make the game feel better to play Evil. In the case of the buggy jump, the Gravity Multiplier, which is normally 1.15, is 1.0. So naturally Leilani can jump higher.

4. Find out why the value is wrong

By watching the gravity value during the playback, I could see the point where it changed value was when Leilani transitioned from one area to the next.



The easiest way to pinpoint the bit of code that changes the value is with a data breakpoint. These can be set up in Visual Studio. The data breakpoint will pause execution of the game when a certain value in memory is changed. This can be a lifesaver in various situations, definitely a tool worth learning to use if you program in C++!



The gravity value was being changed here:



This PositionAtEntrance function is called to place the player entity at the entrance location when moving to a new part of the level. So this is all logical, when moving to the next area, Leilani's gravity multiplier becomes 1.0, the incorrect value. The tricky part is that the gravity multiplier will then only be reset to the correct value (1.15) when Leilani's state changes - for example if she stops rolling, or gets hurt, or bumps into a block. This explains why the bug was hard to reproduce, as the high jump is only possible when moving consistently without stopping or bumping into things.

5. Why did I write this?

So the code looks obviously wrong, but if possible it's nice to double-check why it was written in the first place. This part of the process applies both for code written by someone else, or for code written by yourself a long time ago (there isn't much difference between these two types of code). I use SVN source control for my code, so I can use SVN's Blame tool to look at the log message that I wrote when I last changed that line of code.





I wrote the code in February. The relevant bit seems to be "Debug skipping to next section now prefers any entrance called "Entrance"". I have a debug feature that pressing the + key immediately warps Leilani to the next area in the level, positioning her at one of the entrances to that area. Presumably I ran into a problem with using this debug feature at a time when Leilani's gravity was an unusual value, so I added this code to ensure her gravity was set up correctly after moving to the next area. When I wrote this code I must have forgotten that Leilani's gravity is normally 1.15 (an unintuitive value), not 1.0.

6. The fix



Easy, I already had Leilani's normal gravity value defined at the top of the file; I should have written the code like this in the first place. An easy oversight though.

7. Test

Naturally it's important to give the gameplay a quick test to try and check that I haven't unintentionally broken anything else. Even if a code change seems pretty innocuous, it's surprising the knock-on effects it can have.

I have a test level already set up for testing transitions between areas in all directions. It all seems to work fine, including the jumping-up-to-next-area kind of transition, which is good.



I didn't show it in this gif but I also performed the test with the gravity multiplier value displayed on screen, to double check it looked sensible throughout.

8. Commit it

The fix gets committed into SVN. I wrote a nice log message to explain the bug, so if I did break something today, in the future I'll be able to find out why I changed the code in the first place!



This was a really simple bug example, but hopefully seeing the process I followed is interesting.
Logged

Anton
Level 0
***


View Profile
« Reply #852 on: July 20, 2018, 03:27:05 PM »

I can only admire your dedication.
Both the game and the devlog are amazing!
Not only are you making a game that seems really cool but also you are documenting the process with a magnificent precision.

Thank you so much

This last post really make me whant to try out making a game in C Smiley
Logged

r0ber7
Level 2
**


i like games


View Profile WWW
« Reply #853 on: July 21, 2018, 05:08:20 AM »

I read this devlog when I'm looking for motivation for my own game. I'm not so consistent with devlog updates, but it's also a long term project. So it gives me great joy to see that you are still going, because I am too.  Beer!
Logged

MondayHopscotch
Level 0
*


View Profile
« Reply #854 on: July 22, 2018, 04:43:11 PM »

I'm fairly sure I've read through almost all of this dev log, and it's been a delight. One thing I've been wondering is how you are handling your collisions as a whole. If you've already discussed this, I apologize for missing the post. -- What algorithm are you using for collision detection? I've implemented some basic Separating Axis Theorem collisions in other projects, but it has led me to be very curious how you've approached collision detection.
Logged
Ishi
Pixelhead
Level 10
******


coffee&coding


View Profile WWW
« Reply #855 on: July 26, 2018, 10:39:24 AM »

Thanks for all the nice words!

I'm fairly sure I've read through almost all of this dev log, and it's been a delight. One thing I've been wondering is how you are handling your collisions as a whole. If you've already discussed this, I apologize for missing the post. -- What algorithm are you using for collision detection? I've implemented some basic Separating Axis Theorem collisions in other projects, but it has led me to be very curious how you've approached collision detection.

Yeah I don't think I've covered collisions in-depth - I started writing something just now but realised it's quite a big topic. I'll probably tackle it across a couple of devlog posts in the near future. Smiley
Logged

qMopey
Level 3
***


View Profile WWW
« Reply #856 on: July 26, 2018, 11:36:05 AM »

I searched last night but didn't actually find it -- did you ever describe your run-time object/entity model? What in your game is comprised of these objects/entities? How do they fit in with your editor, and serialization, if at all? What does it look like to add new gameplay features, enemy types, or other things?
Logged
Josh Bossie
Level 2
**


Fly Safe, Pupper


View Profile WWW
« Reply #857 on: July 26, 2018, 12:08:34 PM »

Very interested to see this collision dev log as well. Platformer collision is always interesting, but I bet it's doubly so in a game with so much object-to-object interaction
Logged

MondayHopscotch
Level 0
*


View Profile
« Reply #858 on: July 26, 2018, 01:36:23 PM »

Thanks for all the nice words!

I'm fairly sure I've read through almost all of this dev log, and it's been a delight. One thing I've been wondering is how you are handling your collisions as a whole. If you've already discussed this, I apologize for missing the post. -- What algorithm are you using for collision detection? I've implemented some basic Separating Axis Theorem collisions in other projects, but it has led me to be very curious how you've approached collision detection.

Yeah I don't think I've covered collisions in-depth - I started writing something just now but realised it's quite a big topic. I'll probably tackle it across a couple of devlog posts in the near future. Smiley

Having made some platformers (mostly in the context of game jams), I've learned enough to get by with collisions -- but they are definitely a deep hole to jump into. Some of your previous posts that cover things like "jumping into the row of blocks and only triggering on the middle one so that the block reaction triggers properly" problem have only deepened my curiosity about how you've written your system. It looks very clean from what I can make of it. It will also be great to hear someone talk about collisions without it just being behind a half-baked, featureless tutorial  Smiley

I look forward to reading what you have to say once you get around to it!

Logged
Ishi
Pixelhead
Level 10
******


coffee&coding


View Profile WWW
« Reply #859 on: July 28, 2018, 05:16:35 AM »

I searched last night but didn't actually find it -- did you ever describe your run-time object/entity model? What in your game is comprised of these objects/entities? How do they fit in with your editor, and serialization, if at all? What does it look like to add new gameplay features, enemy types, or other things?

This could be an interesting thing to cover too; I don't have any fancy tech going on though. For example creating entities from the tiles that are placed in the editor is just done with a huge switch statement Smiley I'll add it to the list of things to cover in the future.
Logged

Pages: 1 ... 41 42 [43] 44 45
Print
Jump to:  

Theme orange-lt created by panic