• Hey Guest! Ever feel like entering a Game Jam, but the time limit is always too much pressure? We get it... You lead a hectic life and dedicating 3 whole days to make a game just doesn't work for you! So, why not enter the GMC SLOW JAM? Take your time! Kick back and make your game over 4 months! Interested? Then just click here!
  • Hello [name]! Thanks for joining the GMC. Before making any posts in the Tech Support forum, can we suggest you read the forum rules? These are simple guidelines that we ask you to follow so that you can get the best help possible for your issue.

Question - Code [SOLVED] I just don't understand Cameras...

G

Guest User

Guest
so i tried setting up a camera today and pretty much borked my project. these are the errors i'm getting... the solutions listed in the thread don't seem to work or are not applicable. (my computer is up to date, drivers are up to date, i have restarted my computer, and i'm not creating a surface using the camera size so i don't see how i'd be creating a surface the size 0,0?)

this all started because i wanted to make a camera that's displays everything a 2x zoom for the entire game--no matter the room--and follows my object 'sys_controller' around. i tried doing it like this:
sys_controller - Create
Code:
CAMERA = camera_create_view(0, 0, WIDTH div 2, HEIGHT div 2, 0, sys_controller, 1, 1, -1, -1);
view_set_camera(0, CAMERA);
sys_controller - Room Start
Code:
view_enabled = true;
view_set_visible(0, true);
sys_controller. - Game End
Code:
camera_destroy(CAMERA);
WIDTH and HEIGHT are macros set to 680 and 360 respectively. this did not work and the width/height of the camera were being considered -1/-1 even after i just created it.
i read in the manual that cameras need to be made global to work from room to room, so i did that and restarted my computer since i'd guess that i had a memory leak the entire time just leaving it an instance variable. it still did nothing, though, so i tried replacing the default camera since that seemed to be what i wanted:
Code:
global.CAMERA = camera_create_view(0, 0, WIDTH div 2, HEIGHT div 2, 0, sys_controller, 1, 1, -1, -1);
camera_set_default(global.CAMERA);
and then the errors linked above started popping up. they pop up even if i delete all the camera code like nothing ever happened so now i can't start my game at this point anyway.

i really don't know what i'm doing wrong at this point and no camera tutorial seems to really make it clear to me how these things work. so i'd appreciate some explanation for what is going on. thanks.
 
What happens if you just put the raw numbers in to the function:

global.CAMERA = camera_create_view(0, 0, 340, 180, 0, sys_controller, 1, 1, -1, -1);

Also, are you creating surfaces anywhere else in your project?

If those errors are popping up even with the camera code deleted, it makes me think there is a surface somewhere else being created with a size of 0,0.
 
G

Guest User

Guest
i tried putting raw numbers in at some point, it was still being created at -1, -1 size. the only time i was able to get it to not be -1,-1 was when i used:
Code:
camera_set_view_size(global.CAMERA, WIDTH, HEIGHT);
on the next line after creating the camera. however, according to show_debug_message tests it would just revert back to -1, -1 almost immediately (probably on going to the next room).

right now i can't check it though because the game won't actually start. i went through and replaced the constants in every surface_create() with actual numbers, but the problem persists? i use surfaces a lot and haven't changed them until just now, so i'm not sure what's going on.
Create
Code:
_surf = 0;
Destroy - Room End - Game End
Code:
if(surface_exists(_surf)) { surface_free(_surf); }
this code is inherited by all 'interface_' objects below
Create
Code:
_surf = surface_create(680, 360);
Alarm[1]
Code:
surface_set_target(_surf);
    draw_clear_alpha(BLACK, 1);
    draw_sprite_stretched(spritemap_portrait, shrine_type, grid_x(31), grid_y(2), 172, 180);
    draw_text_center("You pray at the shrine.", 18);
    draw_text_center(message, 20, color);
surface_reset_target();
Draw GUI
Code:
if(surface_exists(_surf)) {
    draw_surface(_surf, 0, 0); }
else {
    _surf = surface_create(680, 360);
    alarm[1] = 1; }
Create
Code:
_surf = surface_create(680, 360);
Draw GUI
Code:
if(surface_exists(_surf)) { draw_surface(_surf, 0, 0); }
else { draw_clear(BLACK); }
Alarm[1]
Code:
if(!surface_exists(_surf)) { _surf = surface_create(680, 360); }
surface_set_target(_surf);
        draw_clear_alpha(BLACK, 1);
      
    // PART: NPC Portrait
    draw_sprite_stretched(spritemap_portrait, 1, 0, 0, 344, 360);
  
    // PART: NPC Name
        draw_set_color(message_color);
    draw_text_grid(44, 1, "NPC_NAME:");
  
    // PART: Dialogue
        draw_set_halign(fa_center);
    draw_text_ext(grid_x(64), grid_y(3), message[message_current], grid_y(1.15), grid_x(38));
        draw_set_color(WHITE);
  
    // PART: Page Instructions
        draw_set_halign(fa_left);
        gpu_set_blendenable(TRUE);
    if(message_current < message_length - 1) {
    draw_text_grid(63, 28, "Press   To Continue  ",LGREY);
    draw_text_grid(63, 28, "      E             >", g.gui_color); }
    else {
    draw_text_grid(63, 28, "Press   To Exit  ",LGREY);
    draw_text_grid(63, 28, "      E         >", g.gui_color); }
        gpu_set_blendenable(FALSE);
surface_reset_target();

alarm[1] = -1;
Create
Code:
surface_layer_splatter = surface_create(680, 360);
surface_set_target(surface_layer_splatter);
    draw_clear_alpha(WHITE, 1);
surface_reset_target();
Draw
Code:
if(!surface_exists(surface_layer_splatter)) {
    surface_layer_splatter = surface_create(680, 360);
    surface_set_target(surface_layer_splatter);
        draw_clear_alpha(WHITE, 1);
    surface_reset_target(); }
else {

    var view_x = camera_get_view_x(view_camera[0]);
    var view_y = camera_get_view_y(view_camera[0]);
    gpu_set_blendenable(TRUE);
    gpu_set_blendmode_ext(bm_zero, bm_src_color);
        draw_surface_part(surface_layer_splatter, view_x, view_y, 340, 180, view_x, view_y);
    gpu_set_blendmode(bm_normal);
    gpu_set_blendenable(FALSE); }
Game End
Code:
if(surface_exists(surface_layer_splatter)) { surface_free(surface_layer_splatter); }
Create
Code:
_surf = surface_create(680, 360);
    alarm[1] = 1;
Draw GUI
Code:
if(!surface_exists(_surf)) {
    _surf = surface_create(680, 360);
    alarm[1] = 1; }
else {
draw_surface(_surf, 0, 0);
Alarm[1]
Code:
surface_set_target(_surf);

draw_clear_alpha(BLACK, 1);

switch(menu_page) {
    case menu.main:
  
    // PART: Page Descriptor
        for(var i = 0; i < array_length_1d(menu_nameBlurb); i++) {
            draw_text_center(menu_nameBlurb[i], 10 + i); }
          
    // PART: Entry Verification Notice
            if(!menu_valid) { draw_text_center("Employee Already On File", 18, LRED); }
          
    // PART: Page Instructions
            gpu_set_blendenable(TRUE);
            draw_text_center("Press       To Proceed", 20, LGREY);
            draw_text_center("      ENTER           ", 20, g.gui_color);
            gpu_set_blendenable(FALSE);
  
    break;
    case menu.query:
  
    // PART: Page Title
        draw_text_center("Have you worked for CONCHEMCOM before?", 10);
      
    // PART: Menu Choice
        switch(menu_cursor) {
            case 0:
                draw_text_grid(v680 - 7, 20, "Yes", DGREY);
                draw_text_grid(v680 + 6, 20, "No", g.gui_color);
                draw_sprite(spritemap_interface, 3, grid_x(v680 + 4), grid_y(20));
            break;
            case 1:
                draw_text_grid(v680 - 7, 20, "Yes", g.gui_color);
                draw_text_grid(v680 + 6, 20, "No", DGREY);
                draw_sprite(spritemap_interface, 3, grid_x(v680 - 9), grid_y(20));
            break;
        default: break; }
      
    break;
    case menu.class:
      
    // PART: Page Title
        draw_text_center("Class Selection", 1);
      
    // PART: Stat Descriptor
        for(var i = 0; i < array_length_1d(menu_statsClass) - 1; i++) {
            draw_text_grid(62, 15 + (i * 2), menu_result[i]); }
  
    // PART: Stat Value
        draw_text_grid(48, 10, menu_class[menu_cursor]);
        for(var i = 0; i < array_length_1d(menu_statsClass) - 1; i++) {
            draw_text_value(70, 15 + (i * 2), menu_statsClass[menu_cursor, i], menu_statsClass[menu_cursor, i]); }
      
    // PART: Class Description
        for(var i = 1; i < array_height_2d(menu_detailClass); i++) {
            draw_text_center(menu_detailClass[menu_cursor, i], 25 + i); }
        draw_set_color(LGREY);
            draw_text_center(menu_detailClass[menu_cursor, 0], 25);
  
    break;
    case menu.race:
  
    // PART: Page Title
        draw_text_center("Race Selection", 1);
      
    // PART: Stat Descriptor
        for(var i = 0; i < array_length_1d(menu_statsRace) - 1; i++) {
            draw_text_grid(62, 15 + (i * 2), menu_result[i]); }
  
    // PART: Stat Value
        draw_text_grid(48, 10, menu_race[menu_cursor]);
        for(var i = 0; i < array_length_1d(menu_statsRace) - 1; i++) {
            draw_text_value(70, 15 + (i * 2), menu_statsRace[menu_cursor, i], menu_statsClass[menu_choice[0], i] + menu_statsRace[menu_cursor, i]); }
  
    break;
    case menu.quick:
  
    // PART: Page Title
        draw_text_center("Quick Selection", 1);
  
    break;
    case menu.escape:

    // PART: Page Instructions
            gpu_set_blendenable(TRUE);
        draw_text_center("Press   To Proceed", 22);
        draw_text_center("      E           ", 22, g.gui_color);
            gpu_set_blendenable(FALSE);
  
    break;
default: break; }

surface_reset_target();

alarm[1] = -1;
Destroy - Game End - Room End
Code:
if(surface_exists(_surf)) { surface_free(_surf); }
none of these are at the start of the game so it's very weird that it crashes before the game is even run, normally when i mess up it happens when i get to the part they are created. i can run a blank project so the problem is definitely something with this project though.
Saving project to: C:\Users\NETBOOKUSER\Documents\GameMakerStudio2\japetusrpg\japetusrpg.yyp
"C:\ProgramData/GameMakerStudio2/Cache/runtimes\runtime-2.0.7.110/bin/Igor.exe" -options="C:\Users\NETBOOKUSER\AppData\Local\GameMakerStudio2\GMS2TEMP\build.bff" -- Windows Run

Loaded Macros from C:\Users\NETBOOKUSER\AppData\Roaming\GameMakerStudio2\Cache\GMS2CACHE\japetusrpg_B7B79FE8\macros.json
Options: C:\ProgramData/GameMakerStudio2/Cache/runtimes\runtime-2.0.7.110\bin\platform_setting_defaults.json
Options: C:\Users\NETBOOKUSER\AppData\Roaming/GameMakerStudio2\hipstercapitalist_394071\local_settings.json
Options: C:\Users\NETBOOKUSER\AppData\Roaming\GameMakerStudio2\Cache\GMS2CACHE\japetusrpg_B7B79FE8\targetoptions.json
C:\ProgramData/GameMakerStudio2/Cache/runtimes\runtime-2.0.7.110/bin/GMAssetCompiler.exe /c /zpex /mv=1 /iv=0 /rv=0 /bv=0 /j=4 /gn="japetusrpg" /td="C:\Users\NETBOOKUSER\AppData\Local\GameMakerStudio2\GMS2TEMP" /cd="C:\Users\NETBOOKUSER\AppData\Roaming\GameMakerStudio2\Cache\GMS2CACHE\japetusrpg_B7B79FE8" /zpuf="C:\Users\NETBOOKUSER\AppData\Roaming/GameMakerStudio2\hipstercapitalist_394071" /m=windows /tgt=64 /nodnd /cfg=default /o="C:\Users\NETBOOKUSER\AppData\Local\GameMakerStudio2\GMS2TEMP\japetusrpg_2FDEB954_VM" /sh=True /optionsini="C:\Users\NETBOOKUSER\AppData\Local\GameMakerStudio2\GMS2TEMP\japetusrpg_2FDEB954_VM\options.ini" /cvm /baseproject="C:\ProgramData/GameMakerStudio2/Cache/runtimes\runtime-2.0.7.110\BaseProject\BaseProject.yyp" "C:\Users\NETBOOKUSER\Documents\GameMakerStudio2\japetusrpg\japetusrpg.yyp" /preprocess="C:\Users\NETBOOKUSER\AppData\Roaming\GameMakerStudio2\Cache\GMS2CACHE\japetusrpg_B7B79FE8"
Reading project file....C:\Users\NETBOOKUSER\Documents\GameMakerStudio2\japetusrpg
Reading project file....C:\ProgramData\GameMakerStudio2\Cache\runtimes\runtime-2.0.7.110\BaseProject
Reading config delta 'C:\Users\NETBOOKUSER\Documents\GameMakerStudio2\japetusrpg\options\main\inherited\options_main.inherited.yy'
finished.


C:\ProgramData/GameMakerStudio2/Cache/runtimes\runtime-2.0.7.110/bin/GMAssetCompiler.exe DONE (0)
Release build
OptionsIni
Options: C:\Users\NETBOOKUSER\AppData\Roaming\GameMakerStudio2\Cache\GMS2CACHE\japetusrpg_B7B79FE8\PlatformOptions.json
[Compile] Run asset compiler
C:\Windows\system32\cmd.exe /c ""C:\ProgramData/GameMakerStudio2/Cache/runtimes\runtime-2.0.7.110/bin/GMAssetCompiler.exe" /c /zpex /mv=1 /iv=0 /rv=0 /bv=0 /j=4 /gn="japetusrpg" /td="C:\Users\NETBOOKUSER\AppData\Local\GameMakerStudio2\GMS2TEMP" /cd="C:\Users\NETBOOKUSER\AppData\Roaming\GameMakerStudio2\Cache\GMS2CACHE\japetusrpg_B7B79FE8" /zpuf="C:\Users\NETBOOKUSER\AppData\Roaming/GameMakerStudio2\hipstercapitalist_394071" /m=windows /tgt=64 /nodnd /cfg=default /o="C:\Users\NETBOOKUSER\AppData\Local\GameMakerStudio2\GMS2TEMP\japetusrpg_2FDEB954_VM" /sh=True /optionsini="C:\Users\NETBOOKUSER\AppData\Local\GameMakerStudio2\GMS2TEMP\japetusrpg_2FDEB954_VM\options.ini" /cvm /baseproject="C:\ProgramData/GameMakerStudio2/Cache/runtimes\runtime-2.0.7.110\BaseProject\BaseProject.yyp" "C:\Users\NETBOOKUSER\Documents\GameMakerStudio2\japetusrpg\japetusrpg.yyp" /bt=run"
Reading project file....C:\Users\NETBOOKUSER\Documents\GameMakerStudio2\japetusrpg
Reading project file....C:\ProgramData\GameMakerStudio2\Cache\runtimes\runtime-2.0.7.110\BaseProject
Reading config delta 'C:\Users\NETBOOKUSER\Documents\GameMakerStudio2\japetusrpg\options\main\inherited\options_main.inherited.yy'
finished.
Compile Constants...finished.
Remove DnD...finished.
Compile Scripts...finished.
Compile Objects...finished.
Compile Timelines...finished.
Compile Triggers...finished.
Compile Rooms...finished.
Compile Extensions...finished.
Global scripts...finished.
Final Compile...finished.
Saving IFF file... C:\Users\NETBOOKUSER\AppData\Local\GameMakerStudio2\GMS2TEMP\japetusrpg_2FDEB954_VM\japetusrpg.win
Writing Chunk... GEN8
option_game_speed=30
Writing Chunk... OPTN
Writing Chunk... LANG
Writing Chunk... EXTN
Writing Chunk... SOND
Writing Chunk... AGRP
Writing Chunk... SPRT
Writing Chunk... BGND
Writing Chunk... PATH
Writing Chunk... SCPT
Writing Chunk... GLOB
Writing Chunk... SHDR
Writing Chunk... FONT
Writing Chunk... TMLN
Writing Chunk... OBJT
Writing Chunk... ROOM
Writing Chunk... DAFL
Writing Chunk... EMBI
Writing Chunk... TPAGE
Writing Chunk... CODE
Writing Chunk... VARI
Writing Chunk... FUNC
Writing Chunk... STRG
Writing Chunk... TXTR
Writing Chunk... AUDO
Writing Chunk... SCPT
Writing Chunk... DBGI
Writing Chunk... INST
Writing Chunk... LOCL
Writing Chunk... STRG
Stats : GMA : Elapsed=2098.0912
Stats : GMA : sp=0,au=0,bk=0,pt=0,sc=0,sh=0,fo=0,tl=0,ob=0,ro=0,da=0,ex=0,ma=2,fm=0x0


C:\Windows\system32\cmd.exe DONE (0)
DoSteam
Igor complete.
[Run] Run game
Options: C:\Users\NETBOOKUSER\AppData\Roaming\GameMakerStudio2\Cache\GMS2CACHE\japetusrpg_B7B79FE8\MainOptions.json
C:\ProgramData/GameMakerStudio2/Cache/runtimes\runtime-2.0.7.110/windows/Runner.exe -game "C:\Users\NETBOOKUSER\AppData\Local\GameMakerStudio2\GMS2TEMP\japetusrpg_2FDEB954_VM\japetusrpg.win"
!!!!No INI File C:\Users\NETBOOKUSER\AppData\Local\GameMakerStudio2\GMS2TEMP\japetusrpg_2FDEB954_VM/options.ini
Attempting to set gamepadcount to 12
DirectX11: Using hardware device
 
Last edited by a moderator:
First off, you may know this...but it is recommended that you draw to surfaces in the draw event, even if it is possible to do so in other events.

Second, I think you should initialise _surf to -1 rather than 0, as 0 might be a valid index of a surface.

Third, in several of your alarm events, you are assuming the surface exists, that is, you are calling surface_set_target(surf) without first checking if it exists.
- I do notice that you are checking if the surface exists in other events.
- However, the docs say that if a surface is confirmed as existing, that is only guaranteed until the end of that script/event to still exist.

So you need to always check for surface existence before trying to draw to it, everytime.

Fourth, what happened that you found you needed to use alarms there...

I usually just check if the surface exists, if not, create the surface. Then, just draw to the surface.

For example, in your interface_shrine object, I would write it like this:

CREATE EVENT:
Code:
_surf = -1
Draw GUI Event:
Code:
if ( !surface_exists(_surf) )
{
    _surf = surface_create(680, 360);
}

surface_set_target(_surf);
draw_clear_alpha(BLACK, 1);
draw_sprite_stretched(spritemap_portrait, shrine_type, grid_x(31), grid_y(2), 172, 180);
draw_text_center("You pray at the shrine.", 18);
draw_text_center(message, 20, color);
surface_reset_target();

draw_surface(_surf, 0, 0);
 
G

Guest User

Guest
OK
1) first i rewrote everything to what you said, but the errors persisted.
2) i got rid of every surface except the one in 'sys_controller'. the rest were just me trying to draw the stuff only once since it doesn't change at all. the alarm was supposed to keep the surface from being drawn to with the default values since it has to wait until the information is given to the object with the surface. anyway, the errors persisted.
3) i removed every surface, even in 'sys_controller'. there was now no code whatsoever in the project creating, drawing to, checking, or freeing surfaces. but the same errors were still here. :(
4) i removed all the camera and view code (again), but it had no effect.
5) i remembered the issues i was having with texture groups a few weeks ago, so i tried a few arrangements and also just not having any at all (except the default) but this didn't seem to do anything either.

so i don't know what it could be.
 
If you are willing, I can take a look at your project (or a trimmed down version of it) - just link it here, or PM me if you want to keep it private.

Bear in mind its late where I am now, I'll be able to look at it tomorrow, need sleep now.
 
G

Guest User

Guest
eugh i'd rather not make someone look through my mess when i have a backup that's not too outdated. i really do appreciate all the help though.

only problem is i still don't really 'get' cameras.
sys_controller - Create
Code:
g.CAMERA = camera_create_view(0, 0, WIDTH div 2, HEIGHT div 2, 0, sys_controller, 1, 1, WIDTH div 3, HEIGHT div 3);
    view_set_camera(1, g.CAMERA);
sys_controller - Room Start
Code:
view_enabled = TRUE;
camera_set_view_size(g.CAMERA, WIDTH div 2, HEIGHT div 2);
view_set_camera(1, g.CAMERA);
view_set_visible(1, TRUE);
sys_controller - Game End
Code:
camera_destroy(g.CAMERA);
i've set up a show_debug_message thing to show me
Code:
view_camera[1]/g.CAMERA | camera_width*/camera_height*
    * camera_get_view_width/height(g.CAMERA);
on creation:
Code:
73/73|340/180
on room start:
Code:
73/73|-1/-1
i just don't understand how the heck to set this thing up and what i need to do in the beginning of every room to make it work. :confused:
 
Hey there.

I think you might not be going crazy after all. When I switch to a new room, it seems like the camera is destoyed, even though its attached to a global variable.

The documenation says :

Note that cameras are like all dynamic resources and will occupy memory when created. This means that you need to take care not to create cameras unnecessarily and to destroy those that you don't need by calling the function camera_destroy(). This also means that cameras will persist from room to room if assigned to a global variable (they will persist when assigned to instance or local variables too, but you can't access them after changing room, hence the memory leak), so that you can - for example - create a new camera, assign it to a global variable, and then at the start of each room use the camera_set_* functions to set the properties before assigning it to a view port.
I did some tests using the code in your previous post. I'm getting the same result, once switching to a new room, the camera view width is showing -1.

ROOM 1:
Room Creation Code
Code:
global.CAMERA = camera_create_view(0, 0, 480, 360, 0, noone, 1, 1, 480 div 3, 360 div 3);

view_enabled = true;
camera_set_view_size(global.CAMERA, 480 div 2, 360 div 2);
view_set_camera(1, global.CAMERA);
view_set_visible(1, true);
ROOM 2:
Room Creation Code
Code:
view_set_camera(1, global.CAMERA);

view_enabled = true;
camera_set_view_size(global.CAMERA, 480 div 2, 360 div 2);
view_set_camera(1, global.CAMERA);
view_set_visible(1, true);
Draw GUI Event of test object for debug purposes:
Code:
draw_text(5,5, string(view_camera[1]))
draw_text(5,25, string(global.CAMERA))
draw_text(5, 45, camera_get_view_width(global.CAMERA))
draw_text(5, 85, camera_get_view_width(view_camera[1]))
In ROOM 1, the debug text shows some correct values. It shows:
401
401
240
240

When I use room_goto_next(), my debug text then shows:
401
401
-1
-1

If I call camera_create_view() again to assign a new camera to global.CAMERA I then get:
410 <-- new camera id
410
240
240

I even tried destroying the camera at the start of room 2, but it doesnt give any error when I try to assign it to a view port, still get same end result, the -1 values, as if the camera has been destroyed.

If I create a new camera in the 2nd room, it gets created, with a different unique camera id, and it works of course.

So, either its a bug in the way cameras work, or the documentation is not quite correct.

Or we are both not understanding cameras :)

EDIT: I don't get the Win32 errors, which in my experience have been from creating surfaces that are 0,0 big.

Also, I noticed in the other thread, someone fixed it by re-creating the camera in every room, which is what I had to do to make it work here.

Finally, I notice @Mike asked in the other thread you linked to in your first post of this thread for someone to file a bug for this, I'm not sure how to check if there is already a bug filed or not.
 
Last edited:
G

Guest User

Guest
ok then so i create it at the beginning of the room every time now.
sys_controller - Create
Code:
CAMERA = -1;
sys_controller - Room Start
Code:
view_enabled = TRUE;
CAMERA = camera_create_view(obj_player.x + WIDTH div 4, obj_player.y + HEIGHT div 4, WIDTH div 2, HEIGHT div 2, 0, sys_controller, 1, 1, 170, 90);
view_set_camera(1, CAMERA);
view_set_visible(1, TRUE);
sys_controller - Room End
Code:
camera_destroy(CAMERA);
sys_controller - Game End
Code:
camera_destroy(CAMERA);
and this seems to work fine. thank goodness.
the Win32 errors are gone after i rolled back, so i still don't quite know what was causing it since i'm not getting them now.so im not sure if it was a bug or perhaps a corrupted/missing file somehow or idk. :\
 
Top