XHXIAIEIN's Forum Posts

  • You can put Tween actions in Function and check Asynchronous. and use "wait for previous actions" to ensure that the previous tween animation is completed.

    Here is an old example

  • Just a random discussion about AI models.

    MCP (Server) is a hot topic recently. It can connects desktop applications and AI through "Model Context Protocol" to achieve tool automation.

    claudemcp.com

    This is an interesting application combined with productivity tools that I have seen recently.

    - Blender: github.com/ahujasid/blender-mcp

    - Unity: github.com/CoderGamester/mcp-unity

    Of course, I don't know if this can really help creators solve some practical problems. It's just making something that looks very beautiful but is completely different from what I need.

    However, it may be helpful in some special scenarios, especially for dealing with some mechanical, repetitive and boring operations.

    I think this also applies to Construct. And it has an advantage because everything in Construct is in JSON, which is very easy to read by AI. And It looks like its technology stack is very suitable for Construct, such as use typescript

    Imagine having AI in Construct help me automate some things:

    - Search Construct documentation, forums, and find solutions or discussions for me.

    - Import multiple files as different sprites

    - Batch rename sprite animation tables, add labels, add image points, collision polygons.

    - Handle the tedious work of timelines and flowcharts

    - Batch add comments to event tables

    - Quickly insert some cheatsheet template events

    - Write a general Function to process Construct's Array, JSON, and dictionary objects

    If Scirra officially does this, it can also integrate its own AI model package and provide subscribers with a certain amount of OpenAI, Claude, Deepseek, Gemini, etc. quotas every month. It also supports users to connect their own API keys and service interfaces.

    -

  • I made a example.

    ---

    This is a simple counter page.

    Demonstrates how to communicate between the iframe and Construct via postMessage() and addEventListener().

    How to get/set Construct variables in the iframe

    How to get/set iframe variables in Construct

    Webpage

    There is a text showing the counter,

    and 2 buttons.

    Button 1, updates the iframe count only.

    Button 2, updates the iframe count and postMessage() to Construct, makeruntime to set the variable.

    The iframe is also listening for an Event from Construct. and when it is triggered, it will update its counter to the parameter value.

    • Preview
    • html
      <!DOCTYPE html>
      <html>
      <head>
       <style>
       #content {
       display: inline-block;
       border: 1px solid #FF0000;
       padding: 6px;
       }
       </style>
      </head>
      <body>
       <div id="content">
       <p>Count: </p><div id="counter">0</div>
       <button id="ButtonA">Set iframe Only</button>
       <button id="ButtonB">Set C3 Both</button>
       </div>
       <script>
      
       const appData = {
       count: 0
       };
      
       const addCounter = (value = 1) => {
       appData.count = Math.min(appData.count + value, 99);
       displayText();
       };
      
       const setCounter = (value = 0) => {
       appData.count = Math.min(value, 99);
       displayText();
       };
      
       const displayText = () => {
       document.getElementById('counter').innerText = appData.count;
       };
      
       const sendMessage = () => {
       const target = window.location.origin;
       window.parent.postMessage({ type: 'increment', value: appData.count }, target);
       };
      
       document.getElementById('ButtonA').addEventListener('click', () => {
       addCounter(2);
       });
      
       document.getElementById('ButtonB').addEventListener('click', () => {
       addCounter();
       sendMessage();
       });
      
       window.addEventListener('changeDataFromC3', (event) => {
       setCounter(event.detail.value || 0);
       displayText();
       });
      
       document.addEventListener('DOMContentLoaded', () => {
       displayText();
       });
      
       globalThis.appData = appData;
      		
       </script>
      </body>
      </html>
      

    html

    <html>
    	<head>
    		 <style></style>
    	</head>
    	<body>
     <div id="counter">0</div>
     <button id="ButtonA"></button>
     <script>
     document.getElementById('ButtonA').addEventListener('click', () => {
     window.parent.postMessage({ type: 'message', value: value });
     });
     </script>
    </body>
    </html>
    

    postMessage

    const sendMessage = () => {
     const targetOrigin = "*";
     window.parent.postMessage({ type: 'message', value: data}, targetOrigin);
    };
    

    globalThis

     const appData = {
     count: 0
     };
    
    globalThis.appData = appData;
    

    Eventsheet

    Load the page in Construct

    Add Listener Events

    const messageHandlers = {
    	increment: data => {
    		const { value } = data;
    		runtime.globalVars.Variable1 = value; // Set Construct Global Variable
    		console.log(`on message: ${value}`);
    	},
    	default: data => {
    		console.log(`no event: ${data.type}`);
    	}
    };
    
    const handleMessage = ({ data = {} }) => {
    	const { type } = data;
    	(messageHandlers[type] || messageHandlers.default)(data);
    };
    
    window.addEventListener('message', handleMessage);
    

    Signal

    runtime.signal("clear-input");
    

    Some Event for Testing

    Send Event to webpage

    const value = 0;
    const event = new CustomEvent('message', { detail: { value } });
    window.dispatchEvent(event);
    

    Get webpage data via globalThis

    const key = localVars.key; // Construct Local Variable & Function Parameter
    const value = globalThis.appData?.[key] ?? 0; // Set globalThis data
    runtime.setReturnValue(value); // Set Function Return Value
    
    {"is-c3-clipboard-data":true,"type":"events","items":[{"functionName":"getDataFromIframe","functionDescription":"","functionCategory":"","functionReturnType":"number","functionCopyPicked":false,"functionIsAsync":false,"functionParameters":[{"name":"key","type":"string","initialValue":"","comment":""}],"eventType":"function-block","conditions":[],"actions":[{"type":"script","script":"const value = globalThis.appData?.[localVars.key] ?? 0;\nruntime.setReturnValue(value);"}]}]}
  • I make a quick example to demonstrate the use of For-each.

    You will observe that the "red box" all have the same angle.

    When you operate directly on the multiple instance object, you don't need to use For-each.

    Sprite: Set Angle to random(360)

    But if you want to use function/action for multiple instance, you need to use For-each.

    If not, although each object will be executed function, but the results of their execution are the same.

    Sprite: Call Function RotateAction(random(360))

    So, you need to use a For-each to make each sprite to rotate a different Angle.

    For Each Sprite → Call Function RotateAction(random(360))

  • You can try this:

    runtime.callFunction(...localVars["command"]
    .split(",").map(e => e.trim())
    .map(e => (isNaN(e) ? e : Number(e))));

    Add it to a Function and call it with a string parameter.

    {"is-c3-clipboard-data":true,"type":"events","items":[{"functionName":"Call","functionDescription":"","functionCategory":"","functionReturnType":"none","functionCopyPicked":false,"functionIsAsync":false,"functionParameters":[{"name":"command","type":"string","initialValue":"","comment":""}],"eventType":"function-block","conditions":[],"actions":[{"type":"script","script":"runtime.callFunction(...localVars[\"command\"]\n.split(\",\").map(e => e.trim())\n.map(e => (isNaN(e) ? e : Number(e))));"}]}]}
  • Just sharing some of my weird ideas recently:

    When I made event triggers, I made some modular objects and check whether it has a specific child object to gave them specific functions and.

    For example, when I needed this event to show a dialogue, I added the dialogue icon to the trigger.

    The green blocks as triggers, they are all the same, And they don't have any instance variables. when player collision or overlapping trigger, check the trigger's hierarchy to see if a specific child object exists.

    In each child icon, there are instance variables that determine what events they will trigger.

    Some of the instructions are:

    • trigger when entering the area
    • Press the interaction key to trigger when overlapping the area
    • Hide after triggering(Destroy but reset at next time when enter the Layout)
    • Permanently remove from current game(Destroy + Persistent & Local Storage)
    • Send signal when trigger

    ~~~

    These icons are from: game-icons.net

  • Try using 'On any touch end' or 'On any touch start' instead of 'On tap' here.

  • I noticed someone posted this example, but it was based on NW.js. Can WebView2 export "transparent background" and "borderless" application modes? Ashley

    Why do we need it?

    This feature allow to make a "desktop ranch" and "desktop pendants" games, like:

    Of course, I know this may be a very difficult work, because that may also warrant attention Technical points:

    1. Borderless windows

    2. Always on top

    3. Allow click-through

    4. Allow background running

    5. Allows movement between different monitors

    6. Notification requested

  • In the for-loop event, we can use wait 0.1 * loopindex seconds to wait for 0.1 second in each loop.

    However, when I try to use loopindex at the same time, it is reset to 0. it is not a static variable in this scope.

    The result is failure:

    The current solution is to add a static variable to record it. But I think this is very troublesome.

    I'm wondering if there is a more elegant way to do it?

  • You can do this using a Tween behavior and playing a 0 - 1 animation using the Tween Value.

    Here is an example: download

  • When I think of Egyptian games, the first thing that comes to my mind is Senet, a very ancient tabletop game. Some people say that Senet is the world's first board game.

    I recall seeing some video games before. I don't know if it has anything to do with egyptian, but I think they may have some very similar aesthetics.

    Chants of Sennaar

    store.steampowered.com/app/1931770

    Heaven's Vault

    store.steampowered.com/app/774201

    Egypt: Old Kingdom

    store.steampowered.com/app/646500

    Lost in Art: a Miniature Realm

    store.steampowered.com/app/2900050

    Apotheon

    (Ancient Greek Mythology)

    store.steampowered.com/app/208750

    Assassin's Creed Origins

    store.steampowered.com/app/582160

    (Wait! also thinking of Temple Run, Zuma, Yu-Gi-Oh! )

  • {"is-c3-clipboard-data":true,"type":"events","items":[{"eventType":"block","conditions":[{"id":"on-any-touch-start","objectClass":"Touch"}],"actions":[{"id":"create-object","objectClass":"System","parameters":{"object-to-create":"DrawingCanvas","layer":"0","x":"Piggy.X","y":"Piggy.Y","create-hierarchy":false,"template-name":"\"\""}},{"id":"set-size","objectClass":"DrawingCanvas","parameters":{"width":"Piggy.Width","height":"Piggy.Height"}},{"id":"paste-object","objectClass":"DrawingCanvas","parameters":{"object":"Piggy","effects":"with-effects"}},{"id":"tween-one-property","objectClass":"DrawingCanvas","behaviorType":"Tween","parameters":{"tags":"\"FadeOut\"","property":"offsetOpacity","end-value":"0","time":"0.3","ease":"easeinoutsine","destroy-on-complete":"yes","loop":"no","ping-pong":"no","repeat-count":"1"}},{"id":"set-animation-frame","objectClass":"Piggy","parameters":{"frame-number":"Self.AnimationFrame+1\n"}}]}]}
    
  • Try Construct 3

    Develop games in your browser. Powerful, performant & highly capable.

    Try Now Construct 3 users don't see these ads
  • You need to use the LocalStorage

    /#open=localstorage-hiscore

    /#open=level-selection

  • You are mixing up the order of the two things you are about to do. You may want to first check if the corresponding userID and password exist in userArray, and if true, stop loop and use localStorage to check the item for this user.

    你可以加QQ群 180911504