malc-game-engine 1.0.2 → 1.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/malc.js +165 -155
  2. package/malc.min.js +18 -16
  3. package/package.json +1 -1
package/malc.js CHANGED
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * MALC Game Engine Library
3
- * Version: 1.0.2
3
+ * Version: 1.0.3
4
4
  * Description: A comprehensive 2D game engine for p5.js
5
5
  */
6
6
 
@@ -40,6 +40,93 @@ function generateId(prefix) {
40
40
  return `${prefix}_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
41
41
  }
42
42
 
43
+ // ========== COLORED TEXT FUNCTION (STANDALONE) ==========
44
+ function coloredText(str, x, y, horizontal, vertical, maxWidth) {
45
+ const p = _p5.prototype; // Use the current p5 instance
46
+ const parts = parseColoredText(str);
47
+ let currentX = x;
48
+ let currentY = y;
49
+
50
+ p.push();
51
+ p.textAlign(horizontal || LEFT, vertical || BASELINE);
52
+
53
+ for (const part of parts) {
54
+ if (part.isNewline) {
55
+ currentX = x;
56
+ currentY += p.textLeading() || p.textSize() * 1.2;
57
+ continue;
58
+ }
59
+
60
+ if (part.color) {
61
+ try {
62
+ p.fill(part.color);
63
+ } catch (e) {
64
+ p.fill(255);
65
+ }
66
+ }
67
+
68
+ p.text(part.text, currentX, currentY, maxWidth);
69
+ currentX += p.textWidth(part.text);
70
+ }
71
+
72
+ p.pop();
73
+ }
74
+
75
+ // Keep these helper functions (they don't need to change)
76
+ function parseColoredLine(str) {
77
+ const regex = /\\([^|\\\n]+)\|([^|]+)\|/g;
78
+ const parts = [];
79
+ let lastIndex = 0;
80
+ let match;
81
+
82
+ while ((match = regex.exec(str)) !== null) {
83
+ if (match.index > lastIndex) {
84
+ parts.push({
85
+ text: str.substring(lastIndex, match.index),
86
+ color: null
87
+ });
88
+ }
89
+
90
+ parts.push({
91
+ text: match[2],
92
+ color: match[1]
93
+ });
94
+
95
+ lastIndex = match.index + match[0].length;
96
+ }
97
+
98
+ if (lastIndex < str.length) {
99
+ parts.push({
100
+ text: str.substring(lastIndex),
101
+ color: null
102
+ });
103
+ }
104
+
105
+ return parts.length ? parts : [{ text: str, color: null }];
106
+ }
107
+
108
+ function parseColoredText(str) {
109
+ const lines = str.split('\n');
110
+ const result = [];
111
+
112
+ for (let i = 0; i < lines.length; i++) {
113
+ const line = lines[i];
114
+ const parts = parseColoredLine(line);
115
+
116
+ result.push(...parts);
117
+
118
+ if (i < lines.length - 1) {
119
+ result.push({
120
+ text: '\n',
121
+ color: null,
122
+ isNewline: true
123
+ });
124
+ }
125
+ }
126
+
127
+ return result;
128
+ }
129
+
43
130
  // ========== SCENE CLASS (DEFINED FIRST) ==========
44
131
  class Scene {
45
132
  static scenes = [];
@@ -84,8 +171,8 @@ class Scene {
84
171
  });
85
172
 
86
173
  _p5.prototype.push();
87
- if (window.camera && typeof camera.render == 'function') {
88
- camera.render();
174
+ if (window.camera && typeof window.camera.render == 'function') {
175
+ window.camera.render();
89
176
  }
90
177
 
91
178
  S.render();
@@ -913,8 +1000,8 @@ class gameObject {
913
1000
  }
914
1001
 
915
1002
  screenToWorld(screenX, screenY) {
916
- if (window.camera && typeof camera.screenToWorld == "function") {
917
- return camera.screenToWorld(screenX, screenY);
1003
+ if (window.camera && typeof window.camera.screenToWorld == "function") {
1004
+ return window.camera.screenToWorld(screenX, screenY);
918
1005
  }
919
1006
  return { x: screenX, y: screenY };
920
1007
  }
@@ -922,9 +1009,9 @@ class gameObject {
922
1009
  isOnScreen() {
923
1010
  if (!window.camera) return true;
924
1011
 
925
- let cameraPos = camera.getOrientation();
926
- let screenRight = cameraPos[0] + camera.width;
927
- let screenBottom = cameraPos[1] + camera.height;
1012
+ let cameraPos = window.camera.getOrientation();
1013
+ let screenRight = cameraPos[0] + window.camera.width;
1014
+ let screenBottom = cameraPos[1] + window.camera.height;
928
1015
 
929
1016
  return (this.x + this.width/2 > cameraPos[0] &&
930
1017
  this.x - this.width/2 < screenRight &&
@@ -1047,42 +1134,45 @@ class Button extends gameObject {
1047
1134
  }
1048
1135
 
1049
1136
  render() {
1050
- if (!this.active) return;
1051
-
1052
- let btnFormat = this.formatting.button;
1053
- let buttonColor;
1054
-
1055
- if (this.isDisabled) {
1056
- buttonColor = btnFormat.colors.disabled;
1057
- } else if (this.isPressed) {
1058
- buttonColor = btnFormat.colors.pressed;
1059
- } else if (this.isHovered) {
1060
- buttonColor = btnFormat.colors.hover;
1061
- } else {
1062
- buttonColor = btnFormat.colors.normal;
1063
- }
1064
-
1065
- let originalColor = this.formatting.color;
1066
- this.formatting.color = buttonColor;
1067
-
1068
- super.render();
1069
-
1070
- if(!this.visible) return;
1071
-
1072
- _p5.prototype.push();
1073
- _p5.prototype.translate(this.x, this.y);
1074
- if (this.rotationMode == "degrees") _p5.prototype.angleMode(_p5.prototype.DEGREES);
1075
- _p5.prototype.rotate(this.rotation);
1076
-
1077
- _p5.prototype.textStyle(btnFormat.text.style);
1078
- _p5.prototype.textSize(btnFormat.text.size);
1079
- _p5.prototype.fill(btnFormat.text.color);
1080
- _p5.prototype.coloredText(btnFormat.text.display, 0, 0, _p5.prototype.CENTER, _p5.prototype.CENTER);
1081
- _p5.prototype.pop();
1082
-
1083
- this.formatting.color = originalColor;
1137
+ if (!this.active) return;
1138
+
1139
+ let btnFormat = this.formatting.button;
1140
+ let buttonColor;
1141
+
1142
+ if (this.isDisabled) {
1143
+ buttonColor = btnFormat.colors.disabled;
1144
+ } else if (this.isPressed) {
1145
+ buttonColor = btnFormat.colors.pressed;
1146
+ } else if (this.isHovered) {
1147
+ buttonColor = btnFormat.colors.hover;
1148
+ } else {
1149
+ buttonColor = btnFormat.colors.normal;
1084
1150
  }
1085
1151
 
1152
+ let originalColor = this.formatting.color;
1153
+ this.formatting.color = buttonColor;
1154
+
1155
+ super.render();
1156
+
1157
+ if(!this.visible) return;
1158
+
1159
+ _p5.prototype.push();
1160
+ _p5.prototype.translate(this.x, this.y);
1161
+ if (this.rotationMode == "degrees") _p5.prototype.angleMode(_p5.prototype.DEGREES);
1162
+ _p5.prototype.rotate(this.rotation);
1163
+
1164
+ _p5.prototype.textStyle(btnFormat.text.style);
1165
+ _p5.prototype.textSize(btnFormat.text.size);
1166
+ _p5.prototype.fill(btnFormat.text.color);
1167
+
1168
+ // Use the standalone coloredText function
1169
+ coloredText(btnFormat.text.display, 0, 0, _p5.prototype.CENTER, _p5.prototype.CENTER);
1170
+
1171
+ _p5.prototype.pop();
1172
+
1173
+ this.formatting.color = originalColor;
1174
+ }
1175
+
1086
1176
  // ========== BUTTON-SPECIFIC HELPER METHODS ==========
1087
1177
 
1088
1178
  setText(text) {
@@ -2265,100 +2355,6 @@ function refreshLoop() {
2265
2355
  });
2266
2356
  }
2267
2357
 
2268
- // ========== COLORED TEXT FUNCTION ==========
2269
- p5.prototype._parseColoredText = function(str) {
2270
- const lines = str.split('\n');
2271
- const result = [];
2272
-
2273
- for (let i = 0; i < lines.length; i++) {
2274
- const line = lines[i];
2275
- const parts = this._parseColoredLine(line);
2276
-
2277
- result.push(...parts);
2278
-
2279
- if (i < lines.length - 1) {
2280
- result.push({
2281
- text: '\n',
2282
- color: null,
2283
- isNewline: true
2284
- });
2285
- }
2286
- }
2287
-
2288
- return result;
2289
- };
2290
-
2291
- p5.prototype._parseColoredLine = function(str) {
2292
- const regex = /\\([^|\\\n]+)\|([^|]+)\|/g;
2293
- const parts = [];
2294
- let lastIndex = 0;
2295
- let match;
2296
-
2297
- while ((match = regex.exec(str)) !== null) {
2298
- if (match.index > lastIndex) {
2299
- parts.push({
2300
- text: str.substring(lastIndex, match.index),
2301
- color: null
2302
- });
2303
- }
2304
-
2305
- parts.push({
2306
- text: match[2],
2307
- color: match[1]
2308
- });
2309
-
2310
- lastIndex = match.index + match[0].length;
2311
- }
2312
-
2313
- if (lastIndex < str.length) {
2314
- parts.push({
2315
- text: str.substring(lastIndex),
2316
- color: null
2317
- });
2318
- }
2319
-
2320
- return parts.length ? parts : [{ text: str, color: null }];
2321
- };
2322
-
2323
- p5.prototype.coloredText = function(str, x, y, horizontal = LEFT, vertical = BASELINE, maxWidth) {
2324
- const parts = this._parseColoredText(str);
2325
- let currentX = x;
2326
- let currentY = y;
2327
-
2328
- const originalFill = this.drawingContext.fillStyle;
2329
- const originalAlign = this.drawingContext.textAlign;
2330
- const originalBaseline = this.drawingContext.textBaseline;
2331
-
2332
- this.textAlign(horizontal, vertical);
2333
-
2334
- for (const part of parts) {
2335
- if (part.isNewline) {
2336
- currentX = x;
2337
- currentY += this.textLeading() || this.textSize() * 1.2;
2338
- continue;
2339
- }
2340
-
2341
- if (part.color) {
2342
- try {
2343
- this.fill(part.color);
2344
- } catch (e) {
2345
- this.fill(originalFill);
2346
- }
2347
- }
2348
-
2349
- this.text(part.text, currentX, currentY, maxWidth);
2350
- currentX += this.textWidth(part.text);
2351
- }
2352
-
2353
- this.fill(originalFill);
2354
- if (originalAlign && originalBaseline) {
2355
- this.drawingContext.textAlign = originalAlign;
2356
- this.drawingContext.textBaseline = originalBaseline;
2357
- }
2358
-
2359
- return this;
2360
- };
2361
-
2362
2358
  // ========== FPS ACCESSOR ==========
2363
2359
  function getFPS() {
2364
2360
  return fps;
@@ -2369,7 +2365,7 @@ const helpDocs = {
2369
2365
  // Game Engine Overview
2370
2366
  overview: `
2371
2367
  MALC Game Engine - A comprehensive 2D game engine for p5.js
2372
- Version: 1.0.1
2368
+ Version: 1.0.3
2373
2369
 
2374
2370
  Core Features:
2375
2371
  - Scene management system
@@ -2561,7 +2557,7 @@ const helpDocs = {
2561
2557
 
2562
2558
  // ========== MALC MAIN OBJECT ==========
2563
2559
  const MALC = {
2564
- version: "1.0.1",
2560
+ version: "1.0.4", // Increment version
2565
2561
 
2566
2562
  // Core classes
2567
2563
  gameObject: gameObject,
@@ -2587,6 +2583,7 @@ const MALC = {
2587
2583
  // Utility functions
2588
2584
  generateId: generateId,
2589
2585
  getTimestamp: getTimestamp,
2586
+ coloredText: coloredText, // Add this line
2590
2587
 
2591
2588
  // Gravity constants
2592
2589
  GRAVITY: GRAVITY,
@@ -2690,26 +2687,39 @@ const MALC = {
2690
2687
  this.mouse = new MouseHandler();
2691
2688
  window.mouse = this.mouse;
2692
2689
 
2690
+
2691
+
2693
2692
  // Start FPS tracking
2694
2693
  refreshLoop();
2695
2694
 
2696
2695
  // Create default scenes
2697
- new Scene("blank", 70);
2698
- new Scene("loading", 50, function(self) {
2699
- _p5.prototype.textSize(24);
2700
- let timed = (self.timeActive / 250 % 4);
2701
- let dots = "";
2702
-
2703
- if (timed < 1) dots = ".";
2704
- else if (timed < 2) dots = "..";
2705
- else if (timed < 3) dots = "...";
2706
-
2707
- _p5.prototype.coloredText(`\\lime|Loading Game${dots}| `, 120, 200, _p5.prototype.LEFT, _p5.prototype.CENTER);
2708
- _p5.prototype.textSize(16);
2709
-
2710
- let num = (Math.floor(self.timeActive / 100) / 10);
2711
- _p5.prototype.coloredText(`\\red|${ Math.round((10 - num) * 10) / 10 + ((num + "").length < 2 ? ".0" : "")}|`, 200, 225, _p5.prototype.CENTER, _p5.prototype.CENTER);
2712
- });
2696
+ // Create default scenes
2697
+ new Scene("blank", 70);
2698
+ new Scene("loading", 50, function(self) {
2699
+ try {
2700
+ _p5.prototype.textSize(24);
2701
+ let timed = (self.timeActive / 250 % 4);
2702
+ let dots = "";
2703
+
2704
+ if (timed < 1) dots = ".";
2705
+ else if (timed < 2) dots = "..";
2706
+ else if (timed < 3) dots = "...";
2707
+
2708
+ // Use standalone coloredText function
2709
+ coloredText(`\\lime|Loading Game${dots}| `, 120, 200, _p5.prototype.LEFT, _p5.prototype.CENTER);
2710
+
2711
+ _p5.prototype.textSize(16);
2712
+
2713
+ let num = (Math.floor(self.timeActive / 100) / 10);
2714
+ let percentText = `${ Math.round((10 - num) * 10) / 10 + ((num + "").length < 2 ? ".0" : "")}`;
2715
+
2716
+ // Use standalone coloredText function
2717
+ coloredText(`\\red|${percentText}|`, 200, 225, _p5.prototype.CENTER, _p5.prototype.CENTER);
2718
+ } catch (e) {
2719
+ // Fallback if coloredText fails
2720
+ _p5.prototype.text(`Loading Game...`, 120, 200);
2721
+ }
2722
+ });
2713
2723
 
2714
2724
  Scene.activeScene = "loading";
2715
2725
 
@@ -2749,4 +2759,4 @@ MALC.mouse = new MouseHandler();
2749
2759
 
2750
2760
  return MALC;
2751
2761
 
2752
- }));
2762
+ }));
package/malc.min.js CHANGED
@@ -1,7 +1,17 @@
1
1
  (function(root,factory){if(typeof define==='function'&&define.amd){define(['p5'],factory)}else if(typeof module==='object'&&module.exports){module.exports=factory(require('p5'))}else{root.MALC=factory(root.p5)}}(typeof self!=='undefined'?self:this,function(p5){const _p5=p5;const MALCgameObjects=[];const MALCbuttons=[];const MALCScene=[];var UIPlanes=[];var buttonsToggled=!0;const GRAVITY=0.5;const TERMINAL_VELOCITY=20;function getTimestamp(){return new Date().getTime()}
2
2
  function generateId(prefix){return `${prefix}_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`}
3
+ function coloredText(str,x,y,horizontal,vertical,maxWidth){const p=_p5.prototype;const parts=parseColoredText(str);let currentX=x;let currentY=y;p.push();p.textAlign(horizontal||LEFT,vertical||BASELINE);for(const part of parts){if(part.isNewline){currentX=x;currentY+=p.textLeading()||p.textSize()*1.2;continue}
4
+ if(part.color){try{p.fill(part.color)}catch(e){p.fill(255)}}
5
+ p.text(part.text,currentX,currentY,maxWidth);currentX+=p.textWidth(part.text)}
6
+ p.pop()}
7
+ function parseColoredLine(str){const regex=/\\([^|\\\n]+)\|([^|]+)\|/g;const parts=[];let lastIndex=0;let match;while((match=regex.exec(str))!==null){if(match.index>lastIndex){parts.push({text:str.substring(lastIndex,match.index),color:null})}
8
+ parts.push({text:match[2],color:match[1]});lastIndex=match.index+match[0].length}
9
+ if(lastIndex<str.length){parts.push({text:str.substring(lastIndex),color:null})}
10
+ return parts.length?parts:[{text:str,color:null}]}
11
+ function parseColoredText(str){const lines=str.split('\n');const result=[];for(let i=0;i<lines.length;i++){const line=lines[i];const parts=parseColoredLine(line);result.push(...parts);if(i<lines.length-1){result.push({text:'\n',color:null,isNewline:!0})}}
12
+ return result}
3
13
  class Scene{static scenes=[];static activeScene="blank";static started=!1;static sceneHistory=[];static historyLimit=10;static update(){this.started=!0;this.scenes=MALCScene;let activeSceneFound=!1;this.scenes.forEach(S=>{if(S.id==this.activeScene){activeSceneFound=!0;this.scenes.forEach(s=>{if(s!=S){s._active=!1;s.active=!1;s.objects.forEach(o=>{if(o&&typeof o.active!=='undefined')o.active=!1})}});S.active=!0;if(!S._active){S.activated=MALC.time.getTime();if(typeof S.onActivate=='function')S.onActivate();}
4
- S._active=!0;S.timeActive=MALC.time.getTime()-S.activated;S.objects.forEach(o=>{if(o&&typeof o.active!=='undefined')o.active=!0});_p5.prototype.push();if(window.camera&&typeof camera.render=='function'){camera.render()}
14
+ S._active=!0;S.timeActive=MALC.time.getTime()-S.activated;S.objects.forEach(o=>{if(o&&typeof o.active!=='undefined')o.active=!0});_p5.prototype.push();if(window.camera&&typeof window.camera.render=='function'){window.camera.render()}
5
15
  S.render();_p5.prototype.pop()}});if(!activeSceneFound&&this.activeScene!="blank"){console.warn(`Scene "${this.activeScene}" not found, switching to blank`);this.activeScene="blank"}}
6
16
  static getSceneById(id){return MALCScene.find(scene=>scene.id==id)||null}
7
17
  static getActiveScene(){return this.getSceneById(this.activeScene)}
@@ -98,9 +108,9 @@ setVelocity(speed,x,y,err=0.5){let angle=this.directionTo(x,y,err);if(isNaN(angl
98
108
  this.velocity=[speed,angle];return this.velocity}
99
109
  destroy(){this.removeFromAllScenes();let index=MALCgameObjects.indexOf(this);if(index>-1){MALCgameObjects.splice(index,1)}}
100
110
  clone(){let clone=new gameObject(this.x,this.y,this.width,this.height,...this.scenes);clone.rotation=this.rotation;clone.rotationMode=this.rotationMode;clone.velocity=[...this.velocity];clone.velocityMode=this.velocityMode;clone.rvm=this.rvm;clone.formatting=JSON.parse(JSON.stringify(this.formatting));clone.gravity=JSON.parse(JSON.stringify(this.gravity));clone.debug=this.debug;clone.hitbox=JSON.parse(JSON.stringify(this.hitbox));return clone}
101
- screenToWorld(screenX,screenY){if(window.camera&&typeof camera.screenToWorld=="function"){return camera.screenToWorld(screenX,screenY)}
111
+ screenToWorld(screenX,screenY){if(window.camera&&typeof window.camera.screenToWorld=="function"){return window.camera.screenToWorld(screenX,screenY)}
102
112
  return{x:screenX,y:screenY}}
103
- isOnScreen(){if(!window.camera)return!0;let cameraPos=camera.getOrientation();let screenRight=cameraPos[0]+camera.width;let screenBottom=cameraPos[1]+camera.height;return(this.x+this.width/2>cameraPos[0]&&this.x-this.width/2<screenRight&&this.y+this.height/2>cameraPos[1]&&this.y-this.height/2<screenBottom)}}
113
+ isOnScreen(){if(!window.camera)return!0;let cameraPos=window.camera.getOrientation();let screenRight=cameraPos[0]+window.camera.width;let screenBottom=cameraPos[1]+window.camera.height;return(this.x+this.width/2>cameraPos[0]&&this.x-this.width/2<screenRight&&this.y+this.height/2>cameraPos[1]&&this.y-this.height/2<screenBottom)}}
104
114
  class Button extends gameObject{static buttons=[];static updateButton(){this.startedButtons=!0;this.buttons=MALCbuttons;this.buttons.forEach(b=>{if(!b.active)return;b.isHovered=b.events.hover();if(MALCbuttons.every(b=>!b.events.hover())){_p5.prototype.cursor()}else if(b.isHovered){_p5.prototype.cursor(b.cursor)}})}
105
115
  static getButtonByIndex(index){return MALCbuttons[index]||null}
106
116
  static getHoveredButton(){return MALCbuttons.find(b=>b.active&&b.events.hover())}
@@ -110,7 +120,7 @@ update(boolean){super.update(boolean);if(this.cooldownActive){let currentTime=Da
110
120
  this.isHovered=this.events.hover();this.isPressed=this.events.pressed();if(this.events.clicked()&&this.onClick&&!this.isDisabled&&!this.cooldownActive){this.onClick(this);this.lastClickTime=Date.now();this.cooldownActive=!0}
111
121
  MALCbuttons[this.buttonIndex]=this}
112
122
  render(){if(!this.active)return;let btnFormat=this.formatting.button;let buttonColor;if(this.isDisabled){buttonColor=btnFormat.colors.disabled}else if(this.isPressed){buttonColor=btnFormat.colors.pressed}else if(this.isHovered){buttonColor=btnFormat.colors.hover}else{buttonColor=btnFormat.colors.normal}
113
- let originalColor=this.formatting.color;this.formatting.color=buttonColor;super.render();if(!this.visible)return;_p5.prototype.push();_p5.prototype.translate(this.x,this.y);if(this.rotationMode=="degrees")_p5.prototype.angleMode(_p5.prototype.DEGREES);_p5.prototype.rotate(this.rotation);_p5.prototype.textStyle(btnFormat.text.style);_p5.prototype.textSize(btnFormat.text.size);_p5.prototype.fill(btnFormat.text.color);_p5.prototype.coloredText(btnFormat.text.display,0,0,_p5.prototype.CENTER,_p5.prototype.CENTER);_p5.prototype.pop();this.formatting.color=originalColor}
123
+ let originalColor=this.formatting.color;this.formatting.color=buttonColor;super.render();if(!this.visible)return;_p5.prototype.push();_p5.prototype.translate(this.x,this.y);if(this.rotationMode=="degrees")_p5.prototype.angleMode(_p5.prototype.DEGREES);_p5.prototype.rotate(this.rotation);_p5.prototype.textStyle(btnFormat.text.style);_p5.prototype.textSize(btnFormat.text.size);_p5.prototype.fill(btnFormat.text.color);coloredText(btnFormat.text.display,0,0,_p5.prototype.CENTER,_p5.prototype.CENTER);_p5.prototype.pop();this.formatting.color=originalColor}
114
124
  setText(text){this.formatting.button.text.display=text;return this}
115
125
  getRGBFromColor(colorInput){let c=_p5.prototype.color(colorInput);return[_p5.prototype.red(c),_p5.prototype.green(c),_p5.prototype.blue(c)]}
116
126
  getBrightness(colorInput){let rgb=this.getRGBFromColor(colorInput);return 0.299*rgb[0]+0.587*rgb[1]+0.114*rgb[2]}
@@ -239,18 +249,10 @@ getButton(name){name=name.toLowerCase();const buttonMap={'select':0,'back':1,'pr
239
249
  return this.buttons[btn]?.pressed||!1}}
240
250
  const controller=new GameController();const fpsTimes=[];let fps;function refreshLoop(){window.requestAnimationFrame(()=>{const now=performance.now();while(fpsTimes.length>0&&fpsTimes[0]<=now-1000){fpsTimes.shift()}
241
251
  fpsTimes.push(now);fps=fpsTimes.length;refreshLoop()})}
242
- p5.prototype._parseColoredText=function(str){const lines=str.split('\n');const result=[];for(let i=0;i<lines.length;i++){const line=lines[i];const parts=this._parseColoredLine(line);result.push(...parts);if(i<lines.length-1){result.push({text:'\n',color:null,isNewline:!0})}}
243
- return result};p5.prototype._parseColoredLine=function(str){const regex=/\\([^|\\\n]+)\|([^|]+)\|/g;const parts=[];let lastIndex=0;let match;while((match=regex.exec(str))!==null){if(match.index>lastIndex){parts.push({text:str.substring(lastIndex,match.index),color:null})}
244
- parts.push({text:match[2],color:match[1]});lastIndex=match.index+match[0].length}
245
- if(lastIndex<str.length){parts.push({text:str.substring(lastIndex),color:null})}
246
- return parts.length?parts:[{text:str,color:null}]};p5.prototype.coloredText=function(str,x,y,horizontal=LEFT,vertical=BASELINE,maxWidth){const parts=this._parseColoredText(str);let currentX=x;let currentY=y;const originalFill=this.drawingContext.fillStyle;const originalAlign=this.drawingContext.textAlign;const originalBaseline=this.drawingContext.textBaseline;this.textAlign(horizontal,vertical);for(const part of parts){if(part.isNewline){currentX=x;currentY+=this.textLeading()||this.textSize()*1.2;continue}
247
- if(part.color){try{this.fill(part.color)}catch(e){this.fill(originalFill)}}
248
- this.text(part.text,currentX,currentY,maxWidth);currentX+=this.textWidth(part.text)}
249
- this.fill(originalFill);if(originalAlign&&originalBaseline){this.drawingContext.textAlign=originalAlign;this.drawingContext.textBaseline=originalBaseline}
250
- return this};function getFPS(){return fps}
252
+ function getFPS(){return fps}
251
253
  const helpDocs={overview:`
252
254
  MALC Game Engine - A comprehensive 2D game engine for p5.js
253
- Version: 1.0.1
255
+ Version: 1.0.3
254
256
 
255
257
  Core Features:
256
258
  - Scene management system
@@ -280,7 +282,7 @@ const helpDocs={overview:`
280
282
  function draw() {
281
283
  MALC.update(); // Updates all MALC systems
282
284
  }
283
- `};const MALC={version:"1.0.1",gameObject:gameObject,Button:Button,Scene:Scene,UIPlane:UIPlane,Camera:Camera,mouse:null,keyboard:keyboard,controller:controller,fps:fps,getFPS:getFPS,time:new Date(),startTime:new Date().getTime(),timer:0,generateId:generateId,getTimestamp:getTimestamp,GRAVITY:GRAVITY,TERMINAL_VELOCITY:TERMINAL_VELOCITY,help:function(topic="overview"){if(topic==="overview"){console.log(helpDocs.overview);return helpDocs.overview}
285
+ `};const MALC={version:"1.0.4",gameObject:gameObject,Button:Button,Scene:Scene,UIPlane:UIPlane,Camera:Camera,mouse:null,keyboard:keyboard,controller:controller,fps:fps,getFPS:getFPS,time:new Date(),startTime:new Date().getTime(),timer:0,generateId:generateId,getTimestamp:getTimestamp,coloredText:coloredText,GRAVITY:GRAVITY,TERMINAL_VELOCITY:TERMINAL_VELOCITY,help:function(topic="overview"){if(topic==="overview"){console.log(helpDocs.overview);return helpDocs.overview}
284
286
  if(helpDocs.classes[topic]){console.log(`=== ${topic.toUpperCase()} ===`);console.log(helpDocs.classes[topic].description);console.log("\nConstructor:",helpDocs.classes[topic].constructor);if(helpDocs.classes[topic].properties){console.log("\nProperties:");Object.entries(helpDocs.classes[topic].properties).forEach(([prop,desc])=>{console.log(` ${prop}: ${desc}`)})}
285
287
  if(helpDocs.classes[topic].methods){console.log("\nMethods:");Object.entries(helpDocs.classes[topic].methods).forEach(([method,desc])=>{console.log(` ${method}: ${desc}`)})}
286
288
  if(helpDocs.classes[topic].staticMethods){console.log("\nStatic Methods:");Object.entries(helpDocs.classes[topic].staticMethods).forEach(([method,desc])=>{console.log(` static ${method}: ${desc}`)})}
@@ -289,6 +291,6 @@ if(helpDocs.input[topic]){console.log(`=== ${topic.toUpperCase()} ===`);console.
289
291
  return helpDocs.input[topic]}
290
292
  if(helpDocs.utilities[topic]){console.log(`=== ${topic.toUpperCase()} ===`);console.log(helpDocs.utilities[topic]);return helpDocs.utilities[topic]}
291
293
  if(topic==="quickStart"||topic==="start"){console.log(helpDocs.quickStart);return helpDocs.quickStart}
292
- console.log(`Help topic "${topic}" not found. Try: overview, classes (gameObject, Button, Scene, UIPlane, Camera), input (mouse, keyboard, controller), utilities (coloredText, getFPS), quickStart`);return null},helpTopics:function(){const topics=["overview","classes: "+Object.keys(helpDocs.classes).join(", "),"input: "+Object.keys(helpDocs.input).join(", "),"utilities: "+Object.keys(helpDocs.utilities).join(", "),"quickStart"];console.log("Available help topics:\n"+topics.join("\n"));return topics},init:function(canvasX,canvasY){_p5.prototype.createCanvas(canvasX,canvasY);this.time=new Date();this.startTime=this.time.getTime();window.camera=new Camera(canvasX,canvasY);this.mouse=new MouseHandler();window.mouse=this.mouse;refreshLoop();new Scene("blank",70);new Scene("loading",50,function(self){_p5.prototype.textSize(24);let timed=(self.timeActive/250%4);let dots="";if(timed<1)dots=".";else if(timed<2)dots="..";else if(timed<3)dots="...";_p5.prototype.coloredText(`\\lime|Loading Game${dots}| `,120,200,_p5.prototype.LEFT,_p5.prototype.CENTER);_p5.prototype.textSize(16);let num=(Math.floor(self.timeActive/100)/10);_p5.prototype.coloredText(`\\red|${ Math.round((10 - num) * 10) / 10 + ((num + "").length < 2 ? ".0" : "")}|`,200,225,_p5.prototype.CENTER,_p5.prototype.CENTER)});Scene.activeScene="loading";console.log("MALC Game Engine initialized v"+this.version);console.log("Type MALC.help() for documentation")},update:function(){this.time=new Date();this.timer=this.time-this.startTime;if(this.mouse){this.mouse.rawX=_p5.prototype.mouseX;this.mouse.rawY=_p5.prototype.mouseY;this.mouse.x=this.mouse.rawX+window.camera.getOrientation()[0];this.mouse.y=this.mouse.rawY+window.camera.getOrientation()[1];this.mouse.down=_p5.prototype.mouseIsPressed}
294
+ console.log(`Help topic "${topic}" not found. Try: overview, classes (gameObject, Button, Scene, UIPlane, Camera), input (mouse, keyboard, controller), utilities (coloredText, getFPS), quickStart`);return null},helpTopics:function(){const topics=["overview","classes: "+Object.keys(helpDocs.classes).join(", "),"input: "+Object.keys(helpDocs.input).join(", "),"utilities: "+Object.keys(helpDocs.utilities).join(", "),"quickStart"];console.log("Available help topics:\n"+topics.join("\n"));return topics},init:function(canvasX,canvasY){_p5.prototype.createCanvas(canvasX,canvasY);this.time=new Date();this.startTime=this.time.getTime();window.camera=new Camera(canvasX,canvasY);this.mouse=new MouseHandler();window.mouse=this.mouse;refreshLoop();new Scene("blank",70);new Scene("loading",50,function(self){try{_p5.prototype.textSize(24);let timed=(self.timeActive/250%4);let dots="";if(timed<1)dots=".";else if(timed<2)dots="..";else if(timed<3)dots="...";coloredText(`\\lime|Loading Game${dots}| `,120,200,_p5.prototype.LEFT,_p5.prototype.CENTER);_p5.prototype.textSize(16);let num=(Math.floor(self.timeActive/100)/10);let percentText=`${ Math.round((10 - num) * 10) / 10 + ((num + "").length < 2 ? ".0" : "")}`;coloredText(`\\red|${percentText}|`,200,225,_p5.prototype.CENTER,_p5.prototype.CENTER)}catch(e){_p5.prototype.text(`Loading Game...`,120,200)}});Scene.activeScene="loading";console.log("MALC Game Engine initialized v"+this.version);console.log("Type MALC.help() for documentation")},update:function(){this.time=new Date();this.timer=this.time-this.startTime;if(this.mouse){this.mouse.rawX=_p5.prototype.mouseX;this.mouse.rawY=_p5.prototype.mouseY;this.mouse.x=this.mouse.rawX+window.camera.getOrientation()[0];this.mouse.y=this.mouse.rawY+window.camera.getOrientation()[1];this.mouse.down=_p5.prototype.mouseIsPressed}
293
295
  controller.update();gameObject.update();Button.updateButton();this.fps=fps;if(typeof window.camera.render=="function"){window.camera.render()}
294
296
  Scene.update()}};MALC.mouse=new MouseHandler();return MALC}))
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "malc-game-engine",
3
- "version": "1.0.2",
3
+ "version": "1.0.4",
4
4
  "description": "A comprehensive 2D game engine for p5.js",
5
5
  "main": "malc.js",
6
6
  "unpkg": "malc.min.js",