Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.


Topics - lawatson

Pages: [1] 2
1
Video Games / Super Cat Planet!
« on: July 11, 2016, 04:30:49 PM »
I've been getting bored lately, and thusly I decided to bring attention to a game series that I actually find particularly fun to stream! The game is Cat Planet alongside its unofficial sequel, Super Cat Planet. Basically, it's an exploration game where you collect all the cats. The graphics, although minimal, are fitting and nice, and the pixel-music isn't half bad either. It's fun both to play casually and blindly and to speedrun. It's actually surprisingly hard getting a decent time with the routing and all.

For starters, I actually suggest you watch raocow's legendary let's play of this game. He's a run-of-the-mill canadian let's player of ROMhacks with a hilarious voice and enthusiastic commentary.

(click to show/hide)

Next up, you can get the game for absolutely free at ludum dare! party like it's 1599! Also, it's made in gamemaker, wow! https://ludumdare.com/compo/ludum-dare-16/?action=preview&uid=1081

Finally, after you've enjoyed the old one to an extent to an extent to an extent, download and play the biggest fan sequel out there right now, Super Cat Planet! It's a lot bigger and quite possibly one of the best things possible if you're a guy who digs exploration, and the difficulty is decent too. I would absolutely recommend a blind playthrough and even a stream to lighten up the mood. Also made in gamemaker (studio this time!), you can get it at raocow's forums. https://talkhaus.raocow.com/viewtopic.php?f=54&t=16025&sid=d83a803fd7eb10e76c9c1d6500a07edf

That concludes the cat planet booster package, so please consider playing it!

2
Video Discussion / I Wanna Be The ↓→↑ - Clear
« on: March 03, 2016, 07:44:25 PM »
httpss://www.youtube.com/watch?v=WXJC9qzwb2Y

Shoutouts to casual and plynq cause they tried this game as much as i did and are the main reason I even tried this boss.

3
Video Discussion / I Wanna Progress Without Purpose: Boss
« on: January 10, 2016, 08:49:32 PM »
https://www.twitch.tv/lawatson/v/31654034

Very hard boss and game made by Plasmanapkin (very good game maker).

Time: 2 hours, Deaths: about 1000-2000.

Strats are very necessary since it is an AI boss with very sudden attacks.

4
Shader Tutorial: Not as baseless as the previous one

Okay, so I'm back from the depths of typing in no-caps, and I've realized that my previous tutorial doesn't really get anywhere. You'll learn how to make a sinewave shader, but you don't really learn anything. Because of that, I've made this current tutorial. I'll scrape out some better and more confident descriptions of how OpenGL ES works and how you can utilize it in Studio. This time, the incoming wall will actually make sense.

Part 1: OpenGL Overview

OpenGL is a coding language which is meant for drawing things to the screen. It's a lot more controllable compared to Studio and if you ever have a surface effect or such which uses too much processing power, then OpenGL is the way to go.

OpenGL operates based on three things: The environment, which is everything outside of OpenGL's code. In this case, it's Gamemaker Studio and all of the variables you set in GMS.
The next thing is the Vertex shader, which gets the position, color, and texture coordinates (research Primitive Drawing in gamemaker) of what'll be drawn in Studio, and then modifies those and passes them on to the final thing, the Fragment Shader.
In the Fragment Shader, everything is drawn based on the information it got from the Vertex shader. Basically, it gets the texture (defined in OpenGL as gm_baseTexture), then it takes the texture coordinates to draw the shape as planned. Each fragment is a triangle which can get its position or color modified.

TL;DR Of Part 1: OpenGL is separate from gamemaker, it uses the Vertex Shader to get the positions, colors, and texture coordinates of the primitive that is drawn, and then passes it on to the Fragment Shader to draw it to the screen.

Part 2: Operating OpenGL

In OpenGL, you have to define a variable using one of many identifiers: "int" is an integer, "float" is any real number, and finally there are "vec2" "vec3" and "vec4", which are vectors with multiple values which are set in parantheses.

Before you define a variable, you need to also define how it is shared. There are "attribute" variables which are the vertices' information which are passed from GMS to the Vertex shader. There are "varying" variables which are shared with the Vertex and Fragment shaders, and there are "uniform" variables which are set within GMS and shared with the shader. You can put a variable as not being shared, and that will mean it gets used in that part of the shader only and will be dumped out after the code is finished.

After all the variables are defined, the arithmetic and code are done in the "main" section of the code. You would start the code like so:
void main()
{
//insert code here
}

The void means that it does the code but doesn't actually return a value, and the main() means that it executes the function which is what you put inside the brackets. Easy enough to understand.

Syntax errors are when something is wrong with the inputs of a function. Most of the time it will be an arithmetic error between two different variable types, so make sure that when doing arithmetic on two variables, they are the same type. You can convert a value to a new type when doing arithmetic by using float(value) or even vec2(value,value). Make sure to properly place the position of arithmetic functions as well, since a variable being set should only be done once but the Main code should handle something like a multiplication for every value of a texture coordinate, stuff like that.

Part 3: GL Variables

There are some variables which OpenGL will use for drawing. I'll just define them here.

in_Position: An attribute vec3 variable which is the position of the vertices. (x,y,z)
in_Colour: An attribute vec4 variable which is the blend color of the vertices. (r,g,b,a)
in_TextureCoord: An attribute vec2 variable which is the coordinates on the TEXTURE. (u,v). Take note that u,v means horizontal, vertical despite the u.

gl_Position: The vec4 position for where OpenGL puts each vertex. (x,y,z,w). The W value will almost always be set to 1.
gl_FragColor: The vec4 color for the fragment drawn. (r,g,b,a). This will be given some more coverage in Part 4.

Part 4: gl_FragColor Overview

Since gl_FragColor is the color of the fragment that is drawn, obviously it won't have significance to the Vertex shader and we should put it in the main code of the Fragment shader instead.

gl_FragColor is the color of the fragments drawn, but it's hard to understand and control. If gl_FragColor is (1,0,0,1), then OpenGL will not actually draw the texture with all red. It will instead just draw a solid red chunk based on the vertices. Unless your ultimate goal all along was to draw a stupid red chunk, then that's a problem. So, what we'll need is the base texture of what is being drawn. We do this with the texture2D() function which inputs a texture and the texture coordinates, and then outputs a brand new colored texture. Now that we have our colored texture, we can then blend it with any color via vec4 multiplication.

In code, our so-wanted red fragment code would look like this.

gl_FragColor = texture2D( gm_BaseTexture, v_vTexCoord) * vec4(1,0,0,1);

v_vTexCoord is a varying variable which we will cover in Part 5. Anyways, this code effectively gets the colored texture of the primitive and makes it retain its red and alpha only. Job well done.

Part 5: Organizing a passthrough shader

A passthrough shader takes the vertex information and passes it onto the fragment shader, and we get our drawn texture, as simple as that. So, how would we make one?

For the vertex shader, we'll of course need to define the position, color, and texture coordinates of the vertices. Using our GL variables from above, we would put that into code like so:

attribute vec3 in_Position;
attribute vec4 in_Colour;
attribute vec2 in_TextureCoord;

Now that we have the values set, we'll need to share that information with the Fragment shader. We'll do this by creating varying variables (covered in Part 2).

varying vec2 v_vTexCoord;
varying vec4 v_vColour;

Now that we've got all the variables we need, we'll set the varying variables within the Main code.

void main()
{
   gl_Position = gm_Matrices[MATRIX_WORLD_VIEW_PROJECTION] * vec4( in_Position, 1);
   
   v_vColour = in_Colour;
   v_vTexCoord = in_TextureCoord;
}

So, we define the position for the primitive as the Gamemaker view (MATRIX_WORLD_VIEW_PROJECTION) times the vertex's x,y,z and 1 as the w value. This gets us the position for the textures on the screen. Next, we define the varying variables as the attribute variables, and those get passed on to the Fragment shader. Job well done.

Now we will make the Fragment shader. We'll need to obtain those varying variables for drawing the fragment correctly, and then we can use those in the Main code for drawing the texture.

varying vec2 v_vTexcoord;
varying vec4 v_vColour;

void main()
{
    gl_FragColor = v_vColour * texture2D( gm_BaseTexture, v_vTexcoord );
}

The fragment's color is equal to the vertex color (white) times the texture, and that's what gets drawn to the screen. Oh boy! We made our fragment shader.

Part 6: Using shaders in GM Studio

This section will be fairly short. This is just how we draw things with shaders and how we set "uniform" variables.

Setting a shader and drawing in Studio is simple enough. You use shader_set(shader name), draw what you want to draw, and then go back to the regular shader with shader_reset().

shader_set(shadertest);
draw_self();
shader_reset();

Setting a uniform in a shader is done with 2 lines of code: Getting the uniform and setting it.

uniform = shader_get_uniform(shader name, "uniform name);
shader_set_uniform(uniform, value);

Like that, you can set a uniform variable to be used in a shader. Now the main overview is done.

Part 7: Messing around in the Fragment Shader

There are multiple ways you can change how the fragments get drawn, including both position and color. For now, we'll go over how texture coordinates work since it is an important thing to know when drawing something. Texture coordinates are the horizontal and vertical positions on a texture. When a texture is drawn to a primitive, it will get "fitted" onto the primitive for drawing. The horizontal and vertical values will range from 0 (the top or left edge) to 1 (the bottom or right edge). You can get a texture coordinate's y and use that to change the texture coordinate's x like a sine wave, and that will greatly effect the outcome result when you are creating the 2D texture for the fragment color.

Honestly, grab the texture coordinates and do whatever you want to them, try experimenting a bit. Now that you know the basics, you should be able to use the correct variable types, what each GL variable means, how to set shaders and uniforms in a shader, and what each function means. I hope you liked this tutorial.

Be sure to tell me how useful this tutorial was, what you learned, what you did and didn't understand. Thanks again for reading.

5
Game Design / Shaders Tutorial (for dummies!)
« on: December 28, 2015, 04:13:13 AM »
shaders tutorial for people too lazy to actually learn opengl, let's do this.

im gonna use no caps except when necessary because my hands are cold and i'm a lazy ass, ok? don't judge. i'm trying my hardest. a final notice, every time i say "(i think)" that means i'm legitimately making a guess and that it's a likely possibility that what i said isn't fucking true and that problems are going to spew everywhere and make a mess. notify me about any problems immediately, ok? thanks buddy.


onto the tutorial.


basically, opengl is its own language (you probably figured that out by now.) it's a crazy world full of variable types and syntax errors, and personally it gives me nightmares. i'll walk you through this fair and square so you don't have to, ok?


variable types

getting started. there's lots of variable types which you need to understand in order to do things correctly. there's 2, 3, and 4-value vectors, which are defined by "vec2", "vec3", and "vec4". they are defined like "vec2 vectorname = (value1, value2)". there's also a lot of different number variables, which personally i hate their existence with all my guts. you've got "int" which is an integer, "bool" which is a true/false value, and "float" which is a real number.


syntax errors

next, there's syntax errors, which are literally gigantic pains in the ass. 90% of the time it'll be because of arithmetic operations on two different variable types, and personally variable type-related errors are ridiculous to me. here's an example of what'll be considered a syntax error:


float two = 2;


perfectly normal, right? well, apparently it's fucking wrong, since it reads 2 as an integer. see what i mean? ridiculous. luckily, the fix is easy (and just as ridiculous): change the 2 to a 2.0 to make it a true float value. there's also arithmetic errors such as 3.5 + 2, since it'll read that as an integer plus a float, which is not okay. to fix that and make it work as wanted, you'll have to change that 2 to a 2.0 yet again. so next time you get a compilation error telling you that you can't add an integer to a float, you'll know how to deal with it. also, adding in constants like pi won't work either since those are seen as read only variables. yep, you have to determine the float value yourself (i think). pretty stupid. anyways, just add a decimal and it should work. onto how shaders work.


how shaders work

shaders have two parts, a vertex and fragment shader. the vertex shader is basically texture coordinates and other texture-related things like color. its purpose is to read the texture's properties and pass them on to the fragment shader which then does the drawing. that's about as simple as it gets.


variable prefixes

now, there's going to be some "variable prefixes" as i like to call them, and they seriously are required if you don't want an infuriating syntax error. the first one is no prefix at all, which means it will only be run in the one shader code (either vertex or fragment, whichever one it appears in). then, there's "attribute" which is the information collected from the texture. then, there's "varying" which means it's a value that gets passed from the vertex code to the fragment code. then, there's "uniform" which gets determined from an outside source (in this case, we use gamemaker functions.) here's how you would define one: "uniform float genericvariable;". this currently won't do anything since nothing defined it, but at least the variable exists now. here's what you would do in gamemaker code:


in the draw event:


shader_set(shadername);
asdf = shader_get_uniform(shadername,asdf);
shader_set_uniform_f(asdf,value);
shader_reset();


or, if you were using a vector and not just a float (or integer???) you would do "shader_set_uniform(asdf,value1,value2)" and so on.


got that? alright. shits gonna get nasty.


passthrough vertex shader

we're gonna work on our vertex shader. we'll make some attribute variables, as follows:


attribute vec3 in_Position;
attribute vec4 in_Colour;
attribute vec2 in_TextureCoord;

varying vec2 v_vTexCoord;
varying vec4 v_vColour;


basically, in_Position is the actual position of the thing, in_Colour is red,green,blue,alpha values of the thing, and in_TexCoord is the coordinates of the texture primitive, which ranges from 0 to 1. the varying variables will be passed on to the fragment shader for it to use, and go figure what they mean lmfao.


now, we're gonna do the actual code, and since openGL is a weirdo we're gonna use this wackass code to begin:


void main()
{
}


see what i mean? edgy shit right there. anyways, in the space between those brackets, we'll have to tell the shader to define the position for the fragment shader to draw, and also determine the values of the varying variables for the fragment shader to use.


void main()
{
   gl_Position = gm_Matrices[MATRIX_WORLD_VIEW_PROJECTION] * vec4(in_Position, 1.0);
   
   v_vColour = in_Colour;
   v_vTexCoord = in_TextureCoord;
}


alright, that was super hard to copypaste so i'll just tell you what all that does from the getgo. basically, the gl_Position variable is for the fragment shader to use to draw all of its shit. we set that to the game's view transformed into the position of the texture. don't try to understand it harder (i think). then, we take those undefined varying variables from earlier and set them in the void main() code so that they get put into the fragment shader as well. speaking of which, that's all done, so let's just paste the whole vertex code and then move onto the fragment:


attribute vec3 in_Position;
attribute vec4 in_Colour;
attribute vec2 in_TextureCoord;

varying vec2 v_vTexCoord;
varying vec4 v_vColour;

void main()
{
   gl_Position = gm_Matrices[MATRIX_WORLD_VIEW_PROJECTION] * vec4(in_Position, 1.0);
   
   v_vColour = in_Colour;
   v_vTexCoord = in_TextureCoord;
}


passthrough fragment shader

now for the fragment code. take mind-note that this code is going to use the stuff it got from the void main() to do the actual drawing. we're not going to do any special twists or turns yet since you don't understand this completely (i predict). here we go.


varying vec2 v_vTexCoord;
varying vec4 v_vColour;


so what we just did right there was we pulled the variable from the vertex shader. this time, though, it'll already have been defined, so go opengl i guess!!!!!! on to the next part of the code. we're going to pull a void main() as before, but you already get that so i'll just post the whole rest of it here.


void main()
{
    gl_FragColor = v_vColour * texture2D( gm_BaseTexture, v_vTexcoord );
}


pretty short, huh? we've already got the gl_Position which it'll use to draw, so now we just need the color set, which just so conveniently is the gl_FragColor variable. it's naturally a vec4 (r,g,b,a), and we set that to the texture's colors * the texture coordinates (primitive coordinates from 0 to 1, NOT the actual positions it will be drawn to lmfao).


so if you use shader_set(shader) and then draw something inside it (be sure to call shader_reset() afterwards) it should pass things right through as if nothing happened.


so all's good in the end, right? nope. we've got a lot fucking more to cover, and shits about to enter a new level of confusing. luckily, i'm still here to un-confuse you. you have the right to sue me if that hasn't held true so far.


example: sinewave shader

we're going to start with a sinewave shader. you know the one. it makes the screen wave around!!! you could do that with surfaces, but let's be honest, that uses a lot of fucking processing power if you make it precise enough, and at that point shaders are our only hope. luckily, we don't even need to change the vertex code this time.


nah, the fragment code is about to get shat on.


we're going to need some special variables for this, ones of the uniform variant. this means we'll be defining these variables inside of gamemaker and not in the actual shader because shaders are run once when drawing something and then everything resets. if you tried to set some special variable which is meant to increase every time the shader is run, that variable would just get dumped straight the fuck out as soon as the fragment shader did its work. luckily, this problem is fixed by using uniform variables. put all this in the fragment code under those other 2 variables:


float xdist;
float ydist;
float two = 1.0;
float pie = 3.14159265;


uniform float time;
uniform float wave_amount;
uniform float wave_distortion;
uniform float wave_speed;


note that four of those variables don't use the uniform prefix (and are particularly weirdly named). this just means that they'll be used in the fragment code only, and the only reason i included them is to avoid syntax errors. anyways, the uniform variables are as follows: time is the radians of the sine wave, wave_amount is the amount of waves (don't be fooled by its description, it actually takes its value in radians), wave_distortion is used to keep the thing being drawn within reasonable bounds (since it'll go fucking nuts otherwise), and finally wave_speed which is just sort of there to see how fast the wave goes. it's okay to cry at this point, since i cried typing this out. we're even now.


now, we've got our unholy monster of a void main() code. i'm prepared to make this as painless as possible, so just follow along and don't try to question anything too much. ready?


void main()
{
    vec2 uv = v_vTexcoord;
    xdist = sin(v_vTexcoord.y*(two*pie)+time*wave_speed);
    vec2 newPos = vec2(xdist/wave_distortion, 0);
    uv += newPos;
    gl_FragColor = v_vColour * texture2D(gm_BaseTexture, uv);
}


alright. maybe it was overhyped. explaining this will be sort of easy, actually. basically, we make a one-time vector called "uv" which is just those same primitive texture coordinates. by the way, "primitive" just sort of means triangle in this case. anyways, now we define a new one time variable, xdist, which is (deep breath) our sinewave! it uses the y position of the texture coordinates (from 0 to 1, primitives, remember???) times the wave_amount (therefore the wave amount in radians will give us exactly however many waves we want). we've now got our sinewave screen, and if you want it to wave around like any human would want to, all you have to do now is add time*wave_speed, which is just the offset.


then, we define a temporary vec2, newPos. it's going to be the change in x of the texture coordinates we'll add to the unchanged variable "uv". it's equal to the xdist/wave_distortion, with the y change being 0 (what did you expect?). the reason it is divided by wave distortion is because instead of the texture coordinates being (0,0) to (1,1), it's going to be from (-1,-1) to (2,2) and that's going to make it three times as expansive as the original texture so we'll just divide it by wave_distortion to smooth the difference down a bit. finally, we add the two vectors uv and newPos, and that becomes the texture that is used in our full-drawn texture.


so, basically, you make that shader and put in that code, and then make an object which sets the shader, grabs those uniform variables, and then sets tham to whatever you want (at this point you can set the time variable so it'll wave around). finally, you can draw the screen or an object or whatever the hell you want. you then just reset the shader and this hell is finally over.


end of actual tutorial

we made it pretty far, huh? nah, you probably decided it was too long and scrolled down here, although i commend your willingness to learn if you did reach this point legitimately. regardless, you ain't gonna get anywhere without reading this thing and getting a basic overview, even if you don't count the optional example (the sinewave shader). don't worry, though, i don't blame you if you did skip all that and just looked at the code all confused-like. we all know how painful it is to absorb a whole bunch of knowledge at once and just sort of have it all squeeze back out, so eat this elephant in however many bites you want.


this ends the tutorial. be sure to give proper feedback, and i don't mean complimenting/hating it. tell me for the love of god how useful it was. saying it was not nice isn't specific enough for me to be able to do anything except give a gigantic "ok". finally, please report any problems you had with this as my lazy ass self was too busy typing this to actually test any of what i just said.


also, if i sounded mean to you in any parts, i didn't mean it. i wouldn't have posted this tutorial just for you in the first place if i was trying to be mean. i want to help gamemakers however i can, you know?


finally, sorry about sounding so melodramatic lmfao, i just lost all actual emotional thinking over the course of today. imagine it as my brain being fried. i ain't normally this monotonous-sounding xd

in retrospect, have a nice day and i hope you learned a lot.

6
User-Made Creations / Apple Star Script
« on: November 27, 2015, 04:06:08 PM »
Not just any apple star creation script, though. Not only does it have what you would normally expect from a star creation code, but it is super controllable too. Like, you can literally micromanage it to such an insane level that I think its existence alone will make aspiring avoidance creators climax in their seats.

Here's the script in its glory:
https://pastebin.com/FLW2fTjW

Or, if you're the type of guy who's too lazy to click it, here's a spoiler with the code instead:

(click to show/hide)

If that's not convincing enough, I think some photographs will change your mind right away.

(click to show/hide)

All of the arguments you can use to control the star are listed inside of the script. If you have the ability to understand the code to its full potential, however, you're free to make special modifications to spice up the star just that much more.

I hope you like it!

also if you experience problems tell me immediately because that would be super problematic lmao

7
Meet and Greet! / Probably should have done this sooner
« on: September 24, 2015, 10:56:10 PM »
Simply doing this because I know new people join the community from time to time and need to get a little overview on everyone here.

Basically, I'm L. A. Watson. Those are my initials. I'm not "lawatson". That's a big thing I need to highlight. You can call me law or watson. I'm okay with that.

I am pretty good at needle (I have completed FTFA screens 1 and 2 and I make hard RMJ maps for fun). I am also decent at avoidance, but definitely not close to the top. I've cleared very few avoidances even though I'm generally good at reading bullets and learning patterns.

In my spare time, I usually laze around, but I also make games. My main highlights are I Wanna Destroy the Yeezy (An avoidance collab between me and CtWw) and Extreme Depths (A needle game made approximately a year ago). I should also highlight that these games are both mediocre (they're not bad, though, I hope...) Over time I have become increasingly good at coding and making games, so I'm confident I'll make better games in the future.

My twitch account is the same as my name (LAWatson). If you want to throw a conversation, you can do it either on twitch or on skype. (Search LAWatson in skype, I have a profile picture from I Wanna Be the Crimson).

I'm generally never doing anything and I don't plan to do anything anytime soon. I just like playing and making games and talking to people. I hope you have fun in this community whether you are new or old, and remember: Please don't cause any unreasonable drama! :atkHappy:

Have a fun time, everyone!

8
Programming Questions / FMOD Help
« on: July 12, 2015, 10:21:33 AM »
I'm not trying to absolutely rewrite the game's sound system to FMOD, but instead just use it to play some specific sounds. No matter what I try, though, it won't play the sound when I try to get it to. Here's the steps I use:

Make a new object similar to the Seph Engine's FMOD loader.
Initialize FMOD correctly.
Add the sound with the SoundAdd function, correct directory and all.
Now switching to the World object.
In End Step Event, I use the FMODUpdate function.

Now I play the sound through a different object, like the player object. It doesn't play. I know it's something with the specific sound and not with FMOD, because when I do it in the Seph Engine which already has everything done, and I add the sound and play it, it doesn't play. Can anyone help me out here?

Another thing to add, I'm taking the sound effects from the K3 sound effects folder. The sounds don't load in Audacity and they can't be converted with an online converter, so I'm wondering if this changes anything.

9
Game Design / For Dummies: Gamemaker Surfaces
« on: June 28, 2015, 04:50:41 PM »
If you're looking at this, that either means that you want to learn how to use surfaces because it sounds interesting, or you just got linked here on accident or something.

A surface in gamemaker is basically a drawing canvas. Just like the game screen, you can draw things on this surface. The difference between surfaces and the game surface is that you can manipulate surfaces in a wide variety of ways while not affecting the game screen. Surfaces are insanely useful in terms of graphics, as they are used for the most complex things like proper lighting engines, screen effects, and even get used in some fangames! (Remember Signore's purple warp?)

So now we know what a surface is, but obviously we're not just here to hear just that. That'd be dumb as crap, so now I'll talk you through the steps of making a surface, drawing to the surface, and manipulating it! Awesome, right? Let's do this.

What we're going to do is make an object which makes each fourth of the screen wave around while also having different colors drawn to each fourth.

Step 1: Making an object for the surface.

Super simple. We'll make an object so that we can define the surface and do all those cool things with it. The recommended qualities for the object are:

Title: oSurfaceWaveScreen
Sprite: No Sprite (We're not gonna be involving a sprite with the surface.)
Visible=1 (We've gotta make the effect visible, right?)
Solid=0
Depth=-100 (The surface will appear over most of the objects on the screen by doing this.)
Persistent=0
Parent: No Parent
Mask: Same As Sprite / No Mask

Step 2: Defining the events and actions.

Create Event:

surf=surface_create(800,608);

//End Of Code

What this does is define the variable "surf" as a newly created surface with a width of 800 and a height of 608.



Room End and Destroy Events:

surface_free(surf);

//End Of Code

What this does is it frees the "surf" surface from the RAM so that we don't end up having another "surf" surface floating around uselessly whenever the game restarts or the room ends.



Step Event:

if !surface_exists(surf){
    surf=surface_create(800,608);
}
surface_set_target(surf);
visible=0;
with(GAMEOVER)visible=0;
screen_redraw();
with(GAMEOVER)visible=1;
visible=1;
surface_reset_target();

//End Of Code

Alright, so now this'll probably seem odd and confusing, so I'll walk you through it.
The reason for this part:

if !surface_exists(surf){
    surf=surface_create(800,608);
}

Is because surfaces are stored in RAM. Normally they'll stay there, but there's always an odd chance that they'll leak out of the memory. In order to make sure that we're always drawing on a surface that exists, we use this code to assure that the "surf" surface exists.

The function surface_set_target() is what sets the surface you'll draw on. If we don't want to draw on the game surface and instead on the "surf" surface, we use this code to make that change.

Now onto the next lines in the code.

visible=0;
with(GAMEOVER)visible=0;
screen_redraw();
with(GAMEOVER)visible=1;
visible=1;

This is confusing for a variety of reasons, but I'll make sure you understand it at its fullest. Basically, it makes the surface invisible, makes the GAMEOVER object invisible, and then redraws the screen. Why this is amazing is because what we're doing isn't actually drawing it on the game surface. We're redrawing the whole entire screen...On the "surf" surface! Since we've copied the screen, we can make the GAMEOVER object visible again and make the surface visible again. That's the reason for this code.

The surface_reset_target() function works almost exactly like the surface_set_target code, but all it does is switches the drawing surface back to the game surface.



Draw Event:

draw_set_color(c_black);
draw_rectangle(0,0,800,608,0);
if surface_exists(surf){
    r+=2;
    for (i=0;i<4;i+=1){
    switch i{
        case 0:
            col=make_color_rgb(255,255,0);
        break;
        case 1:
            col=make_color_rgb(0,255,255);
        break;
        case 2:
            col=make_color_rgb(255,0,255);
        break;
        case 3:
            col=c_white;
        break;
    }
    draw_surface_part_ext(surf,i*200,0,200,608,i*200,32*sin(degtorad(r+(90*i))),1,1,col,1);
    }
}

//End Of Code

This code might look like absolute nonsense to a novice gamemaker coder, but either way I'll make sure you understand it. It's actually not that complex.

draw_set_color(c_black);
draw_rectangle(0,0,800,608,0);

The reason for this is that even though we've got the screen drawn to the surface, we've also got the original screen, unchanged, sitting there behind it. We'll make the original screen blank by putting a gigantic rectangle over it. What we do next is execute the following code whenever the "surf" surface exists:

    r+=2;
    for (i=0;i<4;i+=1){
    switch i{
        case 0:
            col=make_color_rgb(255,255,0);
        break;
        case 1:
            col=make_color_rgb(0,255,255);
        break;
        case 2:
            col=make_color_rgb(255,0,255);
        break;
        case 3:
            col=c_white;
        break;
    }
    draw_surface_part_ext(surf,i*200,0,200,608,i*200,32*sin(degtorad(r+(90*i))),1,1,col,1);
    }

Basically, what we do is increase the variable "r" each frame. We'll use it later.

Aside from that, we start a "for" loop. Basically how it works is it repeats the same code, but each time having "i" be a different value. In that loop, the switch statement checks the variable "i" from the for loop and uses it to set the variable "col" depending on what value "i" is. After that, we draw a part of the "surf" surface. As you should remember, we drew the entire screen onto the "surf" surface, so now we can have our fun with it. Basically, since the "for" loop will repeat 4 times, we draw a different part of the surface 4 times. This is where it gets really tricky to explain.

The arguments for the draw_surface_ext() function are: ID, Left, Top, Length, Height, X, Y, Horizontal Repetition, Vertical Repetition, Color, Alpha.

We're obviously drawing from the "surf" surface.

The left of the part is dependent on "i". Since "i" ranges from 0 to 3, we'll have one part's left be 0, one be 200, and up to 600.

The top of the part is 0. This is so we always draw the correct part of the surface.

The length of every part is 200, because that's exactly 1/4 of the room width.

The height of every part is 608 so we draw the correct part.

The X is also dependent on "i". We won't change this.

The Y position is 32*sin(degtorad(r+(90*i))). This may sound odd, but there's a good reason for this. To make each part wavy, we use the sine function which plots points in a perfect wavy pattern. the degtorad() function simply converts degrees into radians, which is the sine function's way of working. We use the "r" variable as the base degrees, but we also add "i*90" degrees to it. This is how we make the parts wavy.

No extra horizontal or vertical repetition of the part is needed; We're only drawing the part once.

The color is dependent on the "col" variable defined by the switch statement above. Basically, we'll draw one part yellow, one part cyan, one part magenta, and one part white. Gamemaker blends the colors and does amazing things with them.

The alpha is 1, because we need to make it fully visible.

After that, the function is called, the for loop ends, and the code closes.

We'll see what we just created in a gif form! Although, I'd suggest you put it in gamemaker yourself too to see how it affects the screen.

This is what the end result should be similar to:


(click to show/hide)

This concludes the tutorial. This is only getting a certain screen effect, though. You'll have to do a whole bunch of experimentation when you want a fancy screen effect of your own. Now that you know the basics of making a surface, I hope you enjoyed the tutorial!

10
Gameplay & Discussion / Help with IWTTT2
« on: June 21, 2015, 07:18:11 PM »
How do I find the secret areas like Horror World and the Extra Boss? I've looked all over the place, but I can't find the entrances anywhere. Are they in the acts and not the world hubs?

11
Video Discussion / TAS 5th save clear
« on: June 07, 2015, 01:47:21 AM »
Not much of an accomplishment, but it was really fun to do.

https://www.twitch.tv/lawatson/c/6800441

12
Video Discussion / Triple diamond clear!
« on: May 17, 2015, 02:44:29 PM »
https://www.twitch.tv/lawatson/c/6703263
^ Highlight of clearing it

(click to show/hide)
^ Gif of clearing it

Took me like 20 minutes. It was pretty easy. (I updated the gif, too, that means that I actually did it twice)

Oh and also sorry for the loud music, I didn't want silence playing in the stream :c

13
The Lounge / Unnecessary Fangame Accomplishments
« on: March 31, 2015, 10:12:03 PM »
You should be able to gather enough information from the title, but just in case: Post something that was not necessary for progression or you did just for fun.

I'll start with this NANG room 128 alternate route:


14
Gameplay & Discussion / A good explanation about the logic behind aligns
« on: February 03, 2015, 11:18:37 PM »
Let's go over the basics. The player moves 3px per "step" when a directional button is pressed. Let's say the player is on align 0. This means they can go to X = 3,6,9,12,15, and so on. But if they wanted to change their align so they could go to X= 1, 2, 4, or 5, they would have to change their align to 1 or 2. How do you do this? By hitting a wall with that align. Let's see an image regarding the aligns.

Now let's ask our first question: Why do the aligns shift like this? This occurs because since there are 3 possible aligns and the grid is indivisible by 3 (32/3 ≠ integer).
What does this mean? Let's take a more in depth look.


With this, you should understand how you get each align. Now for an explanation regarding offset blocks. Note: this is pretty much an extended example of the first part, which explains how aligns work in the first place.
Chances, although low, are that one of the blocks is offset, with its position maybe 40 or 48. This isn't too complex, because all you're doing by grabbing the align is offsetting it.
Let's take a look at a regular block and an offset block's aligns.
'

There's an explanation for why these two aligns are the same. if the left align's X is 0, that means the far align's X is 24. 24 and 0, when divided by 3 (move speed), result in the decimal point .00, so this means that they are both on align 0.

Now let's look at an offset block which doesn't result in the same align.

The left align's position is 0, and the far align's position is 16. 0/3 is .00 and 16/3 is 5.33 or 1/3. 1/3 * 3 is 1, so it makes sense that the far align is shifted by one pixel.
You can use this guide to basically figure out anything align-related.

That basically covers the align explanation, so I hope you understand now what aligns are and how they work!

Now let's move on to a bonus explanation regarding walk-off aligns!
Walk-off aligns let you walk off a block which has a spike poking out from it. It's only possible with one of the three aligns. But why? The explanation for this is quite complex. The short answer is that it depends on the player's hitbox. If you want the long answer, you can learn about it from the next section.

Here's a failed attempt at a walk-off, where the kid got an align from the block next to them.


Now let's check out the successful attempt, where the kid got an align from the other side of the spike block.


You may or may not be wondering how the player does it with the align farther away from the spike instead of the align closer to the spike. Now we're going to get technical.

Let's see an image of that same thing, but with the align grid.


More specifically, the align which allowed the player to fall through:


The top of the spike where the player can hit is 2px wide.
Let's say that the correct align's X position is 0. That would mean the spike's position is 32. The two kill pixels are at position 32 and 33. With the align, you could go to X=27,30,33,36,39.
Now here's where it gets weird: Though the player's origin, or true position, follows the same 3 pixels as the align, the edge of the hitbox doesn't. The player's regular hitbox is 11px wide, which is not divisible by 3. It's 2px longer than the highest .00 division decimal result, 9. Simply, the edge of the hitbox is extended by two pixels.
 Normally the align in the same block as the spike would be the correct one, but the two edge pixels would collide with the two kill pixels. With the 1px far align, the edge pixels would only collide with the far kill pixel. With the 2px far align, or the correct one, the two edge pixels go beyond the kill pixels, resulting in a successful walk-off! You can use the same logic as this explanation to determine walk-off aligns with different hitbox lengths. I hope this helps you understand!

EDIT: I'm bad at explaining things, so there are probably quite a few things in the post that don't make sense. Try to look past that, though :BloodTrail:

15
Engines / Yuuutu engine with spike difficulty!
« on: January 10, 2015, 11:43:02 PM »
I'm not sure how do describe it, but imagine Bifficult implemented into your engine. That's what this engine is! Enjoy three difficulties of spike.

Download link: httpss://www.dropbox.com/s/bt8n5myz8tjuye6/Yuuutu%20Hard%20Spikes%21.zip?dl=0

Pages: [1] 2