Discord
Login
Community
DARK THEME

Importing classes

Hi all,

I have an awesome javascript game manager that I would like to get running in microStudio as I have replicated MANY functions and a game object handler with built in basic physics etc heavily inspired by Game Maker. I would also like to add this to the public libraries for people to be able to utilize(once it is working, I also would like to know how to upload it).

I have run into an error.

My code is:

init = function() { import * as gm in "isothermalgame"

gm.game_start(); let player = gm.object_add();

player.loop = function(){ player.x += 1; }

let p = gm.instance_create(10, 10, player); }

update = function() { gm.update_game_loop(); }

draw = function() { screen.draw_sprite(sprite, p.x, p.y, 16, 16); }

The error i am getting is saying I cant import outside the module in main.

How can I get this working? Also, how would I upload the library to microStudio for all to use?

Thanks in advance!

Ok so instead of import, i used gm = new isothermalgame();

but now the error is: gm.game_start is not a function, in file "main" at line 4 gm.update_game_loop is not a function, in file "main" at line 15 p is not defined, in file "main" at line 19

I feel like I am getting closer, just not close enough!

Ok so I changed all of my 'function fun()' in to 'func = function()' and all variable inside the constructor as 'this.var', and now i'm getting an error: 'Unexpected token '.', in file "lib/synkrown/isothermal/isothermalgame" at line 34'

Even when I remove the variable on that line, it still says that in the console.

https://microstudio.io/i/SynKrown/isothermalgamebackend/

Here's the project file. If anyone has a clue, and can fix it, please help me out. This will benefit the community as well as I once I finish it 😁

JavaScript support was added last - and it has two major problems.

  1. Using "import" and "export" is not possible because your code will be executed in the eval function - the structure of the javascript language prohibits this.

I tried to get around it myself, but I couldn't.

I tried adding a js file as assets but MicroStudio does not allow adding files ending in *.js.

I decided to add the *.js code, but changing the end of the file to *.txt and importing it using the 'import(url)' function - but now the browser was blocking the download, saying that it had blocked the request to eliminate any possible ambiguities (they introduced this in IE 8.0) .

I have one more idea - I'll let you know how it turns out.

  1. MicroStudio does not correctly show code parsing/execution errors. Because your code must go through a call before being added to executable code:
eval( you_code_javascript_string ) .

If parsing and execution are successful, the code is added and can be used.

If there is an error there will always be an error message on line 34.

This makes debugging very difficult.

You need to add the JavaScript code in small fragments and try to run it - if there is an error, it is in the fragment you added. If you add the entire library at once and run it and there is an error - you have no idea where the error is.

How to add large libraries to a project.

The easiest way is to add one file with javascript code. You cannot use the words "import" and "export" in . What to do if the library uses these words?? If the library uses "export"

class ABC{};
DEF(){}
GHI = function(){}
export { ABC, DEF, GHI }

then

you wrap all the code in a function

nameLib = function()[
class ABC{};
DEF(){}
GHI = function(){}
return { ABC, DEF, GHI }
}

and from the main file

init = function(){
name = nameLib()
}

now the entire library is under the "name" variable.

See the code I moved >>

https://microstudio.io/i/Loginus/three/

https://microstudio.io/i/Loginus/pixi3d/

https://microstudio.io/i/Loginus/consolelog/

https://microstudio.io/i/Loginus/quickengineinjs/

However, it is worse when there are many files and they have the word "import" in them. Now, to add them correctly, you need to wrap each file in a function that returns what you export. You also need to call them in the right order so as not to open the file XYZ which requires classes and functions from the MNO file.

Dang I see what you mean. Yeah the lack of debugging is an annoying thing with javascript. I have a fair bit of code to go through to find the bug lol. Looking through your files, i have tried to replicate a lot of the structure but still not working. is there any chance you could have a wee look at the javascript file in the project I commented above and see if by your logic it should work?

I appeciate the help. I havent done programming in so long im having to get back into the swing of things.

The code will not work because it uses the word "Import" which is only allowed at the top level (before any other javascript code).

When you open the browser console "Ctrl-Shift-I" - you will see the message. " SyntaxError: import declarations may only appear at top level of a module " If you want to display all browser console messages in the MicroStudio console, you can capture them using my "Console.log JS" library.

Version for MicroScript

https://microstudio.io/i/Loginus/consolelog/

JavaScript version.

https://microstudio.io/i/Loginus/consolelogjs/

If your code is not secret, show it or a fragment of it and we will try to port it.

Here's a code paste of my code

https://pastecode.io/s/egk8n4da

I did remove the import line on the main but I think its something to do with my structuring, but I just can't pinpoint it.

I'll have a look at your console log library too. It sounds like a valuable tool to have

Scratch that, I just went through the code of the QuickEngine.js you have there and it has most of the features and more than I was putting into mine. So I might just start with that.

In the QuickEngine source I saw the tile map drawing look and I want to make it more efficient by only drawing the ones on the screen. I have done this before for a terraria generation template in construct 3 so I know the pseudo code, but I need to be able to get the viewport with, height, x and y(like from top left, not center).

Also, can I use QuickEngine with pixi.js? Cause I'm gonna start off with the faster render option

Changing the reference point

screen.setTranslation( tx, you )

Changing the anchor

screen.setDrawAnchor( x, y )

https://microstudio.dev/i/JimB007/screencoords/ << Example of using setTranslation and setDrawAnchor

https://microstudio.dev/i/osterberg/screentools/

You can connect Quick Engine and PIXI. I worked on such a project. This was supposed to be the next stage of Quick Engine + JS development. But I abandoned the project because I decided to combine PIXI.js + Matter.js in one project.

I have to dig out this project.

What's the easiest way to connect Quick Engine and PIXI? Just remove all references to the "screen" graphics and replace them with adding Sprites to the scene. PIXI will draw itself.

You must be very knowledgable in javascript AND microStudio. Thank you again for such detailed explainations. You are an asset to this community.

I will get to working on this. Why reinvent the wheel eh? Haha. I am thinking about adding hotspot points to the sprites to hopefully allow for connecting sprites to other sprites hotspots as limbs, and then implementing procedural animation for platform characters, just like in the game Rain World. I have a pretty good idea of how that will work. Should be a fun wee project!

Would you recommend Matter.js over QuickEngine? Or is the object handling different in Matter.js?

https://microstudio.io/i/Loginus/quick_engin_pixi_js/
^^^^^^^ These are my first attempts at combining Quick Engine and PIXI. (I did it a year ago when I first heard about PIXI)

Adding Sprite and creating Tilemap works.

The rest does not work (e.g. adding subtitles).

The PIXI graphics engine and the Matter physics engine are combined to achieve a similar effect to Quick Engine, but with increased performance. It has to be simple and small.

https://microstudio.io/PaulSt/mattertest2/ << best demo

https://microstudio.dev/i/gilles/matterjstest/

https://microstudio.dev/i/JmeJuniper/physicstest/

Ok apparently i'm not done trying lol.

this.gameManager = function()
{
  objects = []; // Hold a list of game objects
  
  /*
  Game Object class
  */
  gameObject = function(x1, y1, w1, h1)
  {
      x = x1; // Object x position
      y = y1; // Object y position
      z = 0; // Object z position, to be used to sort the depth
      width = w1; // Object width
      height = h1; // Object height
      name = "test"; // The string name of the object
      
      instances = []; // Hold instances of this object for grouping
    
      // Add an instance of this object (called in gameManager.instanceCreate())
      instanceCreate = function(x, y)
      {
        let i = instances.push(new gameObject(x, y, this.width, this.height));
        
        return (i);
      }
      
      // Update the game object
      update = function()
      {
        
      }
      
      return (this);   
  }
  
  // Add an object to the object list
  objectAdd = function()
  {
    let o = objects.push(new gameObject(0, 0, 0, 0));
    
    return (o);
  }
    
  // Add an instance of a created object with the ID of id
  instanceCreate = function(id, x, y)
  {
    let i = id.instanceCreate(x, y);
    
    return (i);
  }
    
  return (this);
}

This is the code I am trying to get running for basic object and instance management. I am clear of errors when testing, but when trying to grab the x or y position of an instance created i = instance_create(obj, 16, 16); it returns 'undefined'.

It would be cool if the javascript side of the engine could work separate to the microscript so we could just write in pure javascript in the main file lol.

My main code works now when I reference the array of objects manually, but when using the variable that is supposed to return the game objet, it shows undefined. Curious as to why it is not referencing the game object from the array;

init = function() {
  catchConsole();
  
  m = isoMath();
  g = gameManager();
  
  o = g.objectAdd();
  ob = g.objectAdd();
  
  g.objects[0].name = "testtickles";
  
  //i = g.instanceCreate(o, 32, 32);
  //i.name = "test";
}

update = function() {
  g.objects[0].x = m.pulse(1000, 64);
  g.objects[0].name = m.to_int(g.objects[0].x);
}

draw = function() {
  screen.clear(m.rgb(128,0,0));
  screen.drawSprite("icon", g.objects[0].x, 0, 16, 16);
  
  screen.drawText(g.objects[0].name, 0, 32, 8, m.rgb(0, 0, 0));
}

Place a link to the entire project and make it public.

Through much trial and error, I seem to have figured out a solution.

this.gameManager = function()
{
  this.objects = []; // Hold a list of game objects
  
  /*
  Game Object class
  */
  this.gameObject = function(id, x1, y1, w1, h1)
  {
      this.id = id;
      this.x = x1; // Object x position
      this.y = y1; // Object y position
      this.z = 0; // Object z position, to be used to sort the depth
      this.width = w1; // Object width
      this.height = h1; // Object height
      this.name = "test"; // The string name of the object
      
      this.instances = []; // Hold instances of this object for grouping
    
      // Add an instance of this object (called in gameManager.instanceCreate())
      this.instanceCreate = function(x, y)
      {
        return(this.instances.push(new gameObject(x, y, this.width, this.height)));
      }
      
      // Update the game object
      this.update = function()
      {
        
      }
      
      return (this);
  }
  
  // Add an object to the object list
  this.objectAdd = function()
  {
    var id = objects.length;
    objects.push(new gameObject(id, 0, 0, 0, 0));
    
    return (objects[id]);
  }
    
  // Add an instance of a created object with the ID of id
  this.instanceCreate = function(id, x, y)
  {
    let i = id.instanceCreate(x, y);
    
    return (i);
  }
    
  return (this);
}

I had to add an index identifier variable in the gameObject, and assign that index based on the array length and return the array position based on the identifier. I thought Array.push would return the index of the item but it certainly does not!

Now I can create an object and reference the variables inside the object without manually referencing the array.

Sorry for wasting your time, but this solution being here might help others encountering similar issues.

array push - the added element is always at the end of the list and the length of the list is returned. If there was no return value, the code did not execute properly.

Code converted to classes:


this.gameManager = function() {
  class GameObject {
    constructor(id, x1, y1, w1, h1) {
      this.id = id;
      this.x = x1; // Object x position
      this.y = y1; // Object y position
      this.z = 0; // Object z position, to be used to sort the depth
      this.width = w1; // Object width
      this.height = h1; // Object height
      this.name = "test"; // The string name of the object
      this.instances = []; // Hold instances of this object for grouping
    }

    // Add an instance of this object (called in gameManager.instanceCreate())
    instanceCreate(x, y) {
      return (this.instances.push(new GameObject(x, y, this.width, this.height)));
    }

    // Update the game object
    update() {
      
    }
  }

  class GameManager {
    constructor() {
      this.objects = []; // Hold a list of game objects
    }

    // Add an object to the object list
    objectAdd() {
      var id = this.objects.length;
      this.objects.push(new GameObject(id, 0, 0, 0, 0));
      return (this.objects[id]);
    }

    // Add an instance of a created object with the ID of id
    instanceCreate(id, x, y) {
      let i = this.objects[id].instanceCreate(x, y);
      return (i);
    }
  }

  return new GameManager();
};

Ok thank you. So would you recommend classes over nested functions for this type of thing? I used classes when I used to work in C#, but javascript is such a versatile language than i've generally gone with the functions inside functions lol

I prefer code with classes because:

  • they are more clear to me
  • it's easier for me to write code divided into classes
  • now javascript language strongly supports classes
  • easier transfer of code between different languages

I have gone over the code you updated for me so I can better understand how to utilize the classes. And I agree, it looks far more organized using classes. You have given me a great template to build off. I have implemented a simple physics system with velocity, friction, gravity and gravity direction. Much more to add yet but all of the code from my javascript game manager I was originally trying to implement seems to be transferring perfectly.

Thank you again for your help!

Post a reply

Progress

Status

Preview
Cancel
Post
Validate your e-mail address to participate in the community