csanyk.com

video games, programming, the internet, and stuff

Tag: GameMaker Studio

YoYoGames: GameMaker Studio 1.4 sunset annonced for 2018

Today, YoYoGames announced that GameMakerStudio 1.4 support will sunset in 2018.

Over the next 14 months, until 31 July 2018, we will continue to mend major issues and support platform updates for Studio 1.4. After the 14-month period, Studio 1.4 will still function normally however, we cannot guarantee it will remain compatible with every platform’s future updates.

While this day has been expected to come since the release of the 2.0 beta back in November 2016, this is quite a bit sooner than expected. YoYoGames support for the 8.x version of GameMaker continued for years after GameMakerStudio 1.0 was released, only ceasing very recently.

It’s not entirely bad for the company to focus itself on development and support for the latest version of their product, but it’s unfortunate for users who for whatever reason are not able to move to the new version so quickly. This also makes it all the more important that GMS2 be as good as it can be. Hopefully, by focusing on the latest version exclusively, this will enable YYG to develop it even faster, adding new features, fixing bugs, and addressing UX issues with the brand new IDE.

Writing files in GameMaker Studio

The levels in TARJECTORIES are procedurally generated, using a lot of calls to the Random Number Generator. Since the output of the RNG is stable for a given seed, the only variability from one runtime to another is the number of calls made to the RNG. Since the number of calls to the RNG in TARJECTORIES is deterministic, this gives the game the same random procedurally generated levels each time the game is played. Fortunately, those levels aren’t too bad to play.

The RNG sequence will vary if you die and play a new game without quitting/relaunching the game, but if you do quit/relaunch it will be the same sequence of levels every time.

I became worried that the game was too sensitive to the RNG, and wanted to capture the level data so that I could re-generate any of the levels in the procedurally generated sequence if I wanted to, even if the game ends up getting modified in such a way that the number of RNG calls changes, which would otherwise screw up the level generation.

To that end, I just wrote up a little script that writes the level data to a .json file, and played through the game, going through two cycles of the 18 procedurally generated levels, so I could get the original sequence plus the level sequence from GE Mode. This was pretty straightforward, except the part about where GameMaker writes the file.

It’s complicated and not easy to understand. GameMaker runs sandboxed, so you can’t just write files anywhere you want. There’s documentation that explains this in the manual, but even after reading it several times, it’s still not entirely clear where you should look to find a file.

My intent in this post isn’t to write a tutorial that guides you to a complete understanding of where GMS writes its files, but I will explain how I found the location.

GML has a built-in variable, working_directory, which is a path on the filesystem where the game.exe is running. The confusing thing about working_directory is that it can return two different values. In certain contexts, the working directory is literally the location where the game.exe is located. You can read files from here, so if you have any “included files” in your project that you need to read from, this is where they’ll be. The thing is, this location is read-only (to GameMaker) so you can’t have your application write any data here, not even to update existing included files. You have a separate location where GameMaker (and all well-behaved Windows applications) can write files, in %LocalAppData%.

This is where it gets weird for me, and I still don’t entirely understand what’s going on.

I run the project out of GMS, and to help me find the file I’m writing, I draw the working_directory to the screen, and I get this:

C:\Users\XXXXX\AppData\Local\gm_ttt_20698\gm_ttt_1803\

So I go there, and I do not see the file that I wrote!

Eventually, I found the file I was looking for in C:\Users\XXXXX\AppData\Local\[project_ name]

I was able to find it because I went to %LocalAppData%, sorted by date last modified, and looked for the most recently updated directory until I found it.

What’s the first directory, then? That’s where GMS builds your project when you run it through the IDE! GMS also uses %LocalAppData% to store the temporary build that it creates when you click Run Project. But this is the read-only working_directory location that is where the game.exe resides. The game.exe then creates its own directory in %LOCALAPPDATA% which is named whatever you named your project (eg., [project_name]) and this is the directory that GMS will allow itself to write to. And of course you can also read files from here, too.

The confusing bit is when you call working_directory in the context of, say, draw_text(x, y, working_directory) and working_directory returns the read-only path, but when you call working_directory in the context of fileID = file_text_open(working_directory+"file.txt");
file_text_write_string(fileID, "text")
, working_directory returns the writeable path.

The behavior of working_directory is what’s confusing. It would be a good idea, I think, if YYG were to create a GML variable called “working_directory_writeable” which was an alias of the writeable working_directory that always returns the writeable path. There should then also be a companion variable called working_directory_readonly They could leave the behavior of working_directory as it is, to avoid breaking anything already written. It can return the readonly directory or the write-able directory, just as it does currently. But if you need to be sure the path to the writeable directory, then you could use “writing_directory”.

So, moral of the story, if your your GameMaker Studio project wrote a file to working_directory, you will find it in C:\Users\XXXXX\AppData\Local\[project_ name] — not the location given by working_directory if you draw it to the screen.

iMprOVE_WRAP 2.1 released

iMprOVE_WRAP 2.1 has been released. Get it at GameMaker Marketplace or itch.io.

Full Documentation.

Release Notes:

1.0 Initial release
1.0.1 Updated iw_draw_self_wrap() to use image_blend rather than c_white for the color argument.
2.0.0 Added new functions:

  • iw_draw_sprite_wrap(): an iMprOVE_WRAP version of draw_sprite()
  • iw_draw_sprite_ext_wrap(): an iMprOVE_WRAP version of draw_sprite_ext()

Improvements:

  • Boundary drawing now occurs at wrap corners as well.
  • Phantom collison checking also occurs at wrap corners.
  • iw_collision_wrap() and iw_collision_wrap_map() functions now incorporate do_wrap_h and do_wrap_v arguments, and only perform collision checks where they are needed. They still return a value for all locations, but where no check is needed, they return noone.
2.0.1 Improvements:

  • iMprOVE_WRAP demo resources have been placed in folders to keep them tidy when importing the asset into a project.
  • oIMprOVE_WRAP_demo sprite has been updated to allow for more precise positioning. Sprite is semi-transparent, with a yellow pixel at the origin
  • oIMprOVE_WRAP_demo object now draws guide lines indicating the height and width of the wrap range. This is useful in confirming that clone drawings and wrapping is occuring where it should.
  • iMprOVE_WRAP demo dashboard text has been updated to be a bit more clear
2.1 New functions:

  • iw_distance_to_object(): returns the shortest distance to the target object from the wrapping object, taking into account all directions available.
  • iw_distance_to_point(): returns the shortest distance to the target point from the wrapping object, taking into account all directions available.

New demo room for the iw_distance_to_object() and iw_distance_to_point() functions

 

GameMaker Studio 2 nearing release

In the last couple of days, YoYoGames have released some teasers that seem to be signaling the immanent release of GameMaker: Studio 2.0. This long-awaited release will overhaul the GM:S GUI, which YoYo have been rewriting in modern C++, and usher in a new era for GameMaker. Beyond that, little is known, as YoYo have been pretty secretive about their plans for the future of GameMaker since being acquired by PlayTech in 2015.

My greatest hope is that GM:S2 will have builds for Mac OS X and Linux. Out of all the software I use today, GameMaker is the last product that runs only on Windows, and I am eager to move to Linux full-time.

It remains to be seen what the release will bring.

Recent purchases of GameMaker who picked it up through the Humble Bundle have been speculating about what GM:S2 will cost. Obviously, a major release isn’t going to be free. It’s typical practice for software companies to sell upgrades to existing users at a substantial discount, so I’m expecting no less.

If YYG do extend discounted upgrade pricing to Humble buyers, most of whom paid around $15, they’ll still be getting an incredible value.

YoYoGames: “No roadmap for GM:S. Our Hands Are Tied!”

For a long time, YoYoGames used to publish a roadmap, showing their plan for the future of GameMaker: Studio. Interested parties could look and see what new features were in the works.

Since PlayTech took them over, they’ve taken this information offline.

In a recent Forum conversation, YoYoGames employees Shaun Spalding and Mike Dailly explained that while they wish they could communicate the future of the product, their hands are tied, and when they can talk about things like upcoming release dates and new features, they will.

This is very disappointing to serious GameMaker Studio users. A roadmap is an important document for developers. Software development is all about maintainability. In order to write software that is maintainable, it’s important to know how the tools you are using will be changing over time. Knowing the future plans of the tools can help developers avoid wasting time using features that will be deprecated and removed in the future, or avoid wasting time writing their own implementation of a feature that is planned in an upcoming version. A roadmap also prevents the repeated asking of the same questions, “when is [X] coming out?” or “I suggest you implement [already planned feature].” A roadmap is part of the conversation that happens between a software developer and the users, and not having one harms both the company and its customers.

Most software engineering projects intended to be consumed by other developers have a roadmap. Other game engine developers such as Unity3D and Godot Engine have public roadmaps.

It is my hope that PlayTech will change their policies surrounding information of their products, and allow their employees to engage in open conversation about their products. In the meantime, concerned GameMaker users should speak out and make their voices heard.

iMprOVE_WRAP extension for GameMaker Studio

Today I’ve released a new asset on the YoYoGames Marketplace, called iMprOVE_WRAP.

Many video games have the feature that exiting one side of the screen will “wrap” you around to the opposite side — notable examples of this include the smash hit classics Asteroids and Pac Man. GameMaker: Studio has a GML function, move_wrap(), which is intended to provide this feature easily, but it has a few limitations. iMprOVE_WRAP addresses these limitations, resulting in a more powerful, flexible implementation.

iMprOVE_WRAP improvements over move_wrap()

Wrap behavior is no longer based on the built-in GML speed variables.

One of the most troublesome limitations of move_wrap() is that it only works for instances that have a speed. In standard GML, the variables speed, hspeed, and vspeed are used to move instances. But you can also “move” an instance by changing it’s x and y position in the room, without setting a speed. Many GM:S users will implement their own movement systems that eschew these variables, in order to give themselves complete control over the movement engine. When they do so, they are often confused when they discover that move_wrap() doesn’t do what they expect.

iMprOVE_WRAP eliminates this dependency, so that an instance no longer need to use the GML speed variables in order to wrap; wrap behavior in iMprOVE_WRAP is based entirely on an instance’s x,y position.

iMprOVE_WRAP_animation

Wrap region no longer limited to room borders

Another problem with move_wrap() is that it is intended to work with the Outside Room or Intersect Boundary GML Events. This means that move_wrap() is only useful when an instance moves outside the room, or encounters the edge of a room. But in many games, the “play field” may not be synonymous with the entire room — the room might have a border, or “dashboard” or “heads up display” which ideally should be considered “out of bounds” with regard to the play field.

iMprOVE_WRAP allows you to define a “wrap region” — a rectangular area inside the room, which instances wrap around the borders of, rather than the borders of the room.

Independent horizontal, vertical margins

With move_wrap() the margin argument which determines the margin by which the instance must be outside of the room is the same for both horizontal and vertical travel; with iMprOVE_WRAP the horizontal and vertical margins may be set independently of each other.

Wrapping instances can (optionally) draw themselves on both sides of the border

With move_wrap(), an instance still draws its sprite in the default draw in only one location: at (x,y). If the instance is off the edge of the wrap boundary, but hasn’t yet crossed over, the instance draws on the “pre-wrap” side of the room; after the instance progresses by margin pixels over the border, then the instance’s position is moved over to the “post-wrap” side of the room, and the instance is drawn there. This is not a big deal if the instance crosses the wrap boundary quickly, and has a relatively small sprite; but for slower-moving instances, or instances with larger sprites, it creates a jarring “jump” effect, where suddenly the instance appears on the “post-wrap” side of the boundary, with no real warning, rather than gradually entering the room.

iMprOVE_WRAP solves this by providing a new function, iw_draw_self_wrap(). This new function augments the default draw by drawing the calling instance four additional times, at positions left, right, up, and down from the actual instance, the width or height of the wrap region away from the actual instance. Thus, when your wrapping instance is moving off the edge of the wrap region, one of these extra drawings is poking out on the opposite side, creating an illusion of continuity as the instance leaves one side and emerges from the other.

For a wrap region that is smaller than the room itself, it’s best to do your drawing on a surface that is sized to the area of the wrap region; otherwise the parts of the drawing that should be outside of the region will be visible outside of the wrap region. Alternately, if drawing to a surface is not something you want to do, you can “mask off” the portions of the room outside of the wrap region by layering objects at a higher depth around the border, like a picture frame or dashboard.

Collision detection on both edges of the border

To compliment the iw_draw_self_wrap() function, I’ve added a new collision function, iw_collision_wrap(). This function checks for collisions at the four places occupied by the four drawings drawn by iw_draw_self_wrap(). There are actually two iw_collision_wrap() functions.

The more basic, iw_collision_wrap() sets five instance variables in the calling instance to store the id of any instance in collision: other_center, other_up, other_down, other_left, and other_right.

The more advanced, iw_collision_wrap_map(), returns the id of a ds_map, which holds those same five instance variables as keys, which you can access using ds_map_find_value().

Which to use is up to you, and the style of programming you prefer. iw_collision_wrap() is easier to use, and if you don’t mind the instance variable names, is probably slightly faster at runtime. iw_collision_wrap_map() is for programmers who get pedantic about “correctness” and want their functions to return something, not cause side effects in the application state. Since it’s not possible in GML to have a function return 5 separate values, we return a data structure that stores the five values. The downside of this is that you have some overhead, namely a need to clean up the ds_map when it is no longer needed. Fortunately, it’s not hard. The example project will demonstrate how to do this properly, so don’t worry.

iMprOVE_WRAP is available at the YoYoGames Marketplace for $2.99; however I am making it free for the first 10 downloads. Please rate it and review it if you give it a try!

Get iMprOVE_WRAP

Control Schemes 0.1 released

ControlSchemes1140x360

This is a collection of scripts and macros that handle motion and action. A “control scheme” is a set of inputs and their associated actions. Add a control scheme to your player object with just two lines of code!

It is intended to handles input, motion, and action quickly and easily, while allowing you to extend to include any audio or visual effects that may be needed.

Documentation is awesome.

Currently, just two control schemes are implemented; I’ll be adding others in the future, much more is planned.

It’s currently free, as I’d like to get everyone to try it out and provide me with feedback, but when I’ve added more features I’ll be charging for it, so be sure to get it now while it’s free!

mmap mini maps 1.2 released

Today mmap mini maps 1.2 was released on the GameMaker Marketplace. It’s a really great asset, which ads a powerful, configurable, easy to use mini map system to your GameMaker: Studio project. I’ve spent dozens, if not over a hundred hours developing this asset to the highest quality, and am selling it for just $4.99.

Experience the Live demo in HTML5.

New features:

  1. Vector arrows: configuration option allows moving blips to have an arrow drawn to the map screen showing the direction and relative speed.
  2. Edge blips: configuration option allows distant objects that are out of range to be drawn at edge of map screen, showing the direction to the distant object.
  3. Sound support: configuration option allows for sound effects to be played when a sonar pulse is emitted, or when a radar blip is refreshed.
  4. Room, View Borders: configuration option draws a border to the map screen, showing the edge of the View or Room boundary.
  5. Documentation updated: Includes a new section showing example code to make setting up your oMmap easier than ever before.

Bug fixes:

  1. I noticed that the functions that I had added to the mmap_mini_map.gmez extension are not working. I’m not sure why they are not working, but I have replaced the .gmez functions with Script resources for now, as these do work. This is a temporary workaround, as the Scripts don’t have autosuggest support to tell you what arguments the script takes. Once I have figured out how to get the functions working again, they’ll be converted back. Additional functions to support the oMmap object will be forthcoming at that time. They were planned for 1.2.0, but were held back due to this issue.

mmap mini maps is back in the GameMaker Marketplace

I’ve re-published the mmap mini maps over at the GameMaker Marketplace. The new version, 1.1.6, fixes the bug of the missing mmap constants — this time the right way, replacing the earlier workaround that I had supplied a few days ago.

Building the asset package the way I needed it was not obvious, but with the help from some GameMaker Community Forums users, I was able to learn the correct method to get the constants added to the package.

Two ways to build a Marketplace Asset

GM:S has two ways to build an Asset.

The more visible method of the two, and the one I had used at first when building my Asset, is to use the Package Manager, located in the Marketplace Menu.

Using this method, you can only build an asset which includes “project resources” — Sprites, Sounds, Backgrounds, Paths, Scripts, Shaders, Fonts, Time Lines, Objects, Rooms, or Included Files.

NOT include-able are Extensions, Macros, Game Information, or Global Game Settings. It’s a good idea to understand the rationale for not including these, and how YYG intends for GM:S users to work around these limitations:

  • It makes sense not to be able to include Extensions, because building an Asset is building an Extension, and Extensions are not designed to be nested.
  • Macros cannot be included, but I’m not clear on why. Perhaps because it’s not easy to separate built-in Macros such as GM_version and GM_build_date, and importing these would create conflicts?
  • Game Information is a deprecated legacy feature which YYG seems to be phasing out. No longer can Game Information be displayed at runtime when a game is playing. So it really only serves to exist as a readme file that you can access from within the GM:S IDE, when working on the project. The same information you might put in here is better added to an Included File.
  • Global Game Settings includes a number of fields that are developer-specific, and should not be shared, such as advertising account credentials, Facebook App ID, etc. There are some settings that would be nice if they could be included in an Asset package, such as HTML5 graphics settings, and options for Use New Audio Engine and Short-Circuit Evaluations, but if your Asset depends on such settings, the only option is to document that in your user manual so that users of the Asset can be informed of how they will need to set up their project.

The other way to create an Asset for the marketplace is to build an Extension. Right click on the Extensions folder in the Resource tree of a project, and Create Extension. Then right-click the newly created extension and Add Placeholder. The purpose of a “placeholder” is vague, but what it allows you to do is define Macros which reside at the extension level,which is done one at a time, in an interface that is different from the project-level Macros editor, and even more of a pain to use.

You can also add Functions to the Extension placeholder. You can add a code file, such as exported scripts in .gml format, or a .dll, .js, .dy-lib, etc. and then define Functions which hook up to the code file.

Once the Extension is defined, you can create an Asset out of it, by logging into Marketplace, and then right-clicking the Extension, and choosing the Create Asset Package option. Creating the Asset Package this way is much the same process as creating an Asset Package from the Marketplace menu, with the exception that the Extension that you right-clicked on will be included with the Asset Package.

Why there isn’t a simple way to include an Extension in the Package Manager build process, I don’t know. I guess the answer ultimately is that this is a new feature in GameMaker, and still in beta. The UI design is rough, inconsistent and not as obvious as it could be. Hopefully this will be addressed as the features are refined. But, for now, it is what it is, and game developers who use GM:S will just need to be aware and familiarize themselves with the differences between these two methods of building an Asset Package.

mmap mini maps asset temporarily withdrawn from GameMaker Marketplace

Well, they SAID it’s in beta.

I’ve been struggling with updating my mmap mini maps asset pack in order to fix a bug that I discovered with it. Since I’ve been unable to do so, I’ve elected to temporarily withdraw the product, rather than continue selling a broken asset. I’ll have it back up as soon as I can get it fixed, but I don’t know how long that may take, due to problems I’m having with the tools.

First, the bug. In the mmap mini maps package, there was supposed to have been a collection of Macros (what used to be known until recently as “Constants”), which I used to assist with programming the Mmap object. When I built the Asset Package, I failed to realize that these Macros did not get included. Without the Macros defined, the project doesn’t work.

One workaround would be to add the macros manually. They are documented completely in the user manual that I wrote. I can also furnish a .txt file that can be imported, to save the data entry. If I can’t get the tools to cooperate, that may end up being the solution I go with for the short term.

It was not obvious due to the way the package builder works, and I didn’t notice it in testing because I tested it by bringing the package into the same project that I had used to build it in the first place.

Lesson learned: Build the package in one project. Import the package into a fresh project to test.

Betas gonna beta

When you build an asset package in GameMaker: Studio, you start by taking some project that you’ve been working in, and then going through the Marketplace Package Manager to build a Marketplace Asset using resources from the project. However, the interface that YoYoGames have built is still very beta. It is unstable, resulting in error messages and crashes. But the greater issue is that the design of the interface, and the workflows it supports, is also rather poor and unrefined at the moment.

When you build your Marketplace Asset Package, you are presented with a Package Builder that allows you to select resources from the project and add them to the package. But the resource selection options are not complete. You can’t select Macros. They just aren’t even there.

So how do you add Macros to a Package? By adding them to an Extension, supposedly. There’s an Extension Builder built into the GM:S IDE, as well as this new Marketplace Package builder. I’m presently unclear as to the relationship between Extension builder and Package builder, but the end result of a Package is that you get a package that is ready to be uploaded to the Marketplace as an Asset, and when you download Assets that you’ve purchased from the Marketplace, it installs itself in your Library, where you can add it to a project, where it… becomes an extension.

The Marketplace asset-extension has whatever resources you had added to the Package — sprites, scripts, objects, sound effects, fonts, included files, timelines, shaders, you name it… just no macros.

But if you build an GMEZ extension using the Extension Builder interface, things are very different. I can create an Extension, add a “placeholder” to it, where I can define Macros (one at a time, which is horrible, like each Macro is its own asset in the tree), and I can add a code file, which can be .gml, javascript, a dll, a dy-lib, or java. And I can define Functions which access the code residing in the code file, providing an interface between GM:S and the functions provided by the extension.

And the documentation shows a similar resource picker for handling both importing resources from a completed Extension into the Project, and for moving project resources into an Extension that you’re authoring. But, for some reason when I am in the Extension Builder, it’s one-way only, I can import from the Extension to the project, but not from the project to the extension.

So when I build an Extension, the only things I can put in it are Macros and Functions and Code files. And when I build a Package, the only things I can put into it are project resources other than Macros and Extensions. So I can’t add Macros to an Extension, then add the Extension to the Package. And I can’t add project resources to the Extension Builder. So there’s this impasse that I can’t figure out how to work around.

It could be the documentation is just out of sync with the version of GM:S I’m running, or it could be there’s some serious design bugs in GM:S currently, or it could be I completely misunderstand both the documentation and the user interface, and am missing something that will become apparent to me eventually.

I’m a bit frustrated now, and very tired of banging my head against a wall trying to figure out how to make it work, so I need to step away from it for a short bit.

csanyk.com © 2016
%d bloggers like this: