XHXIAIEIN's Recent Forum Activity

  • I just found that when I opened the C3 editor in iOS Safari, I couldn't drag the event block in the event table. It seemed to lack relevant interaction methods. I looked through the documentation and didn't find any relevant gesture instructions. do I missing some steps? Ashley

    Tagged:

  • You can use SVG in HTML Elements to made this curved text input.

    Here is an example: Curved_Text_Input.c3p

  • > normally a text adventure will be translated to many languages and right now it doesn't allow to be edited outside construct, reconstructing one by one by hand each dialogue is tedious on big storylines.

    You definitely shouldn't make a flowchart per language. Just have one flowchart for all languages, and instead of putting the actual text in the flowchart, just put the key to look up in the Internationalization object.

    Is that what you wanted the save/load JSON feature for? If so you shouldn't need it after all, as using one flowchart for all languages is a better solution.

    I tried a solution, first generate the md5 hash value for the original language, and then generate the JSON file. Other languages ​​also create their own JSON files and use the corresponding hash as the key.

    example: Flowchart_with_Multi-language.c3p

    You only need to maintain a Array/spreadsheet/CSV file:

    en-US, pt-BR, zh-CN
    Home, Início, 主页
    About, Sobre, 关于我们
    

    you can directly use English with the flowchart, and display the text by using a function.

    Functions.Translate("Home")
    Functions.Translate(FlowchartController.OutputValue("Text"))
    

    Then use the tool to automatically generate the JSON file.

    ---

    The working principle of it is that it will generate a Hash for your original language and correspond it with other languages.

    When you search for a language through the Functions, it will first generate a Hash for the original language, and then look for the corresponding Key in the JSON. For the Hash algorithm, the `hashFnv1a64` algorithm is used here, which is very fast and has very small collisions. It is also synchronized and has very little impact on performance.

    This way, you no longer need to use an ID like `home.title` to refer to it.

    en-US.json

    {
     "hash1": "Home",
     "hash2": "About"
    }
    

    pt-BR.json

    {
     "hash1": "Início",
     "hash2": "Sobre"
    }
    
  • You do not have permission to view this post

  • Just provide another idea.

    You can use a delimiter to separate it.

    like: Layout-1, Layout-20

    Then use tokenat expression to get out the number.

    tokenat(LayoutName, 1, "-")
    

    For example:

    tokenat("Layout-5", 1, "-") // 5
    tokenat("Layout 5", 1, " ") // you can also use spaces as delimiters.
    
  • Step1: Add a Array Object

    {
     "books": []
    }
    {"is-c3-clipboard-data":true,"type":"events","items":[{"eventType":"block","conditions":[{"id":"on-start-of-layout","objectClass":"System"}],"actions":[{"id":"set-array","objectClass":"JSON","parameters":{"path":"\"books\"","size":"0"}}]}]}

    -----------------------

    Step2: Add a dictionary Object in the Array

    {
    	"books": [
    		{}
    	]
    }
    
    {"is-c3-clipboard-data":true,"type":"events","items":[{"eventType":"block","conditions":[{"id":"on-start-of-layout","objectClass":"System"}],"actions":[{"id":"set-array","objectClass":"JSON","parameters":{"path":"\"books\"","size":"0"}},{"id":"push-value","objectClass":"JSON","parameters":{"where":"back","path":"\"books\"","value":"0"}},{"type":"comment","text":"add an object/dictionary: {}"},{"id":"set-object","objectClass":"JSON","parameters":{"path":"\"books.\" & 0"}}]}]}

    Here we need to explain,

    The simplest explanation is that you can think of JSON as an enhanced version of Dictionary and Array, which can use the superset object of dictionary {"key": value} and array [0,1,2..] at the same time.

    But when you need to use them, you need to declare whether the path is a dictionary or an array. Therefore, you need to use Set Array and Set Object action to change their types.

    -----------------------

    Step3: Add a Key in the dictionary

    {
    	"books": [
    		{
    			"title": "Everyday Italian"
    		}
    	]
    }
    {"is-c3-clipboard-data":true,"type":"events","items":[{"eventType":"block","conditions":[{"id":"on-start-of-layout","objectClass":"System"}],"actions":[{"id":"set-array","objectClass":"JSON","parameters":{"path":"\"books\"","size":"0"}},{"type":"comment","text":"add a book"},{"id":"push-value","objectClass":"JSON","parameters":{"where":"back","path":"\"books\"","value":"0"}},{"id":"set-object","objectClass":"JSON","parameters":{"path":"\"books.\" & 0"}},{"type":"comment","text":"[b]Set Path[/b] can make the JSON object to enter this path, so that you can use \".title\" to reference the [u]relative path[/u].\n\nIf you don't do this, you need to use an [u]absolute path[/u]: \"books.0.title\""},{"id":"set-path","objectClass":"JSON","parameters":{"path":"\"books.\" & loopindex"}},{"id":"set-value","objectClass":"JSON","parameters":{"path":"\".title\"","value":"\"Everyday Italian\""}}]}]}

    -----------------------

    Step4: Add a More Key

    {
    	"books": [
    		{
    			"title": "Everyday Italian",
    			"authors": ["Giada De Laurentiis"],
    			"year": 2005,
    			"price": "30.00"
    		}
    	]
    }
    

    Note that because authors is an array, you need to use Set Array to change its type.

    {"is-c3-clipboard-data":true,"type":"events","items":[{"eventType":"block","conditions":[{"id":"on-start-of-layout","objectClass":"System"}],"actions":[{"id":"set-array","objectClass":"JSON","parameters":{"path":"\"books\"","size":"0"}},{"type":"comment","text":"add a book"},{"id":"push-value","objectClass":"JSON","parameters":{"where":"back","path":"\"books\"","value":"0"}},{"id":"set-object","objectClass":"JSON","parameters":{"path":"\"books.\" & 0"}},{"id":"set-path","objectClass":"JSON","parameters":{"path":"\"books.\" & loopindex"}},{"type":"comment","text":"info"},{"id":"set-value","objectClass":"JSON","parameters":{"path":"\".title\"","value":"\"Everyday Italian\""}},{"id":"set-array","objectClass":"JSON","parameters":{"path":"\".authors\"","size":"0"}},{"id":"push-value","objectClass":"JSON","parameters":{"where":"back","path":"\".authors\"","value":"\"Giada De Laurentiis\""}},{"id":"set-value","objectClass":"JSON","parameters":{"path":"\".year\"","value":"2005"}},{"id":"set-value","objectClass":"JSON","parameters":{"path":"\".price\"","value":"\"30.00\""}}]}]}

    -----------------------

    Step5: Using Array Object Data

    {"is-c3-clipboard-data":true,"type":"events","items":[{"eventType":"block","conditions":[{"id":"on-start-of-layout","objectClass":"System"}],"actions":[{"id":"request-project-file","objectClass":"AJAX","parameters":{"tag":"\"\"","file":"books.json"}},{"id":"wait-for-previous-actions","objectClass":"System"},{"id":"load","objectClass":"Array","parameters":{"json":"AJAX.LastData"}},{"id":"signal","objectClass":"System","parameters":{"tag":"\"json\""}}]},{"eventType":"block","conditions":[{"id":"on-signal","objectClass":"System","parameters":{"tag":"\"json\""}}],"actions":[{"id":"set-array","objectClass":"JSON","parameters":{"path":"\"books\"","size":"0"}}],"children":[{"eventType":"block","conditions":[{"id":"for","objectClass":"System","parameters":{"name":"\"book\"","start-index":"0","end-index":"Array.Height-1"}}],"actions":[{"type":"comment","text":"add a book"},{"id":"push-value","objectClass":"JSON","parameters":{"where":"back","path":"\"books\"","value":"0"}},{"id":"set-object","objectClass":"JSON","parameters":{"path":"\"books.\" & loopindex"}},{"id":"set-path","objectClass":"JSON","parameters":{"path":"\"books.\" & loopindex"}}],"children":[{"eventType":"block","conditions":[{"id":"for","objectClass":"System","parameters":{"name":"\"info\"","start-index":"0","end-index":"Array.Width-1"}}],"actions":[{"type":"comment","text":"info"},{"id":"set-value","objectClass":"JSON","parameters":{"path":"\".title\"","value":"Array.At(0, loopindex(\"book\"))"}},{"id":"set-array","objectClass":"JSON","parameters":{"path":"\".authors\"","size":"0"}},{"id":"split-string","objectClass":"bookAuthors","parameters":{"string":"Array.At(1, loopindex(\"book\"))","separator":"\",\"","type":"string"}},{"id":"set-value","objectClass":"JSON","parameters":{"path":"\".year\"","value":"Array.At(2, loopindex(\"book\"))"}},{"id":"set-value","objectClass":"JSON","parameters":{"path":"\".price\"","value":"Array.At(3, loopindex(\"book\"))"}}],"children":[{"eventType":"block","conditions":[{"id":"for-each-element","objectClass":"bookAuthors","parameters":{"axes":"x"}}],"actions":[{"id":"push-value","objectClass":"JSON","parameters":{"where":"back","path":"\".authors\"","value":"trim(bookAuthors.CurValue)"}}]}]}]}]}]}

    -----------------------

    Finally, share a little tip.

    When I use JSON, I usually put a Text Input object in the scene and set its Type property to Textarea. Then set Text to JSON.ToBeautifiedString. This way you can easily inspect the contents of the JSON object

    {"is-c3-clipboard-data":true,"type":"events","items":[{"eventType":"block","conditions":[{"id":"every-tick","objectClass":"System"}],"actions":[{"id":"set-text","objectClass":"TextInput","parameters":{"text":"JSON.ToBeautifiedString"}}]}]}
    
  • The mentioned "Hot Update" likely refers to "In-app updates", which are currently very common in large-scale mobile games. Mainstream commercial game engines also provide some mature solutions for this.

    If the content you want to update consists of data files like JSON configurations, remote images, or similar resources, you could directly use AJAX to request these resources from a server and replace the corresponding objects in the runtime.

    But for larger updates, such as event tables, scenes, etc. it is not currently possible in Construct.

    In-app updates also implies risks as it can bypass the platform"s review process and directly publish application updates. Therefore, the Apple Store explicitly prohibits using this method to update games(App Review Guidelines).

    Meanwhile, Google Play offers an In-app updates solution, which might be the closest legitimate approach.

  • Try Construct 3

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

    Try Now Construct 3 users don't see these ads
  • 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

  • You do not have permission to view this post

  • 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))

XHXIAIEIN's avatar

XHXIAIEIN

Member since 26 Mar, 2016

Twitter
XHXIAIEIN has 14 followers

Trophy Case

  • 9-Year Club
  • Jupiter Mission Supports Gordon's mission to Jupiter
  • Forum Contributor Made 100 posts in the forums
  • x2
    Coach One of your tutorials has over 1,000 readers
  • Regular Visitor Visited Construct.net 7 days in a row
  • Steady Visitor Visited Construct.net 30 days in a row
  • Enduring Visitor Visited Construct.net 90 days in a row
  • RTFM Read the fabulous manual
  • x46
    Quick Draw First 5 people to up-vote a new Construct 3 release
  • x10
    Lightning Draw First person to up-vote a new Construct 3 release
  • x10
    Great Comment One of your comments gets 3 upvotes
  • Delicious Comment One of your comments gets 10 upvotes
  • Email Verified

Progress

21/44
How to earn trophies