<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-US"><generator uri="https://jekyllrb.com/" version="4.4.1">Jekyll</generator><link href="https://ulysseszh.github.io/feed/tags/javascript.xml" rel="self" type="application/atom+xml" /><link href="https://ulysseszh.github.io/" rel="alternate" type="text/html" hreflang="en-US" /><updated>2026-04-19T16:48:01-07:00</updated><id>https://ulysseszh.github.io/feed/tags/javascript.xml</id><title type="html"><![CDATA[Ulysses’ trip]]></title><subtitle>Here we are at the awesome (awful) blog written by UlyssesZhan!</subtitle><author><name>UlyssesZhan</name><email>ulysseszhan@gmail.com</email></author><entry><title type="html"><![CDATA[How to use JavaScript in GitHub Actions without committing <code>node_modules</code>]]></title><link href="https://ulysseszh.github.io/guide/2024/11/15/gh-action-modules.html" rel="alternate" type="text/html" title="How to use JavaScript in GitHub Actions without committing node_modules" /><published>2024-11-15T16:34:55-08:00</published><updated>2024-11-15T16:34:55-08:00</updated><id>https://ulysseszh.github.io/guide/2024/11/15/gh-action-modules</id><content type="html" xml:base="https://ulysseszh.github.io/guide/2024/11/15/gh-action-modules.html"><![CDATA[<p>I was creating my first GitHub Action (it is now working, which you can check out <a href="https://github.com/UlyssesZh/grs-action" target="_blank" rel="external">here</a>). I am familiar with JavaScript, so I chose to create a JavaScript action. According to the <a href="https://docs.github.com/en/actions/sharing-automations/creating-actions/creating-a-javascript-action#commit-tag-and-push-your-action-to-github" target="_blank" rel="external">official documentation</a>, I need to do one of the following to make my JavaScript code correctly import 3rd-party modules:</p>
<ul>
<li>commit the <code>node_modules</code> to the repo, or</li>
<li>use <a href="https://github.com/vercel/ncc" target="_blank" rel="external">@vercel/ncc</a> to bundle everything into a single script.</li>
</ul>
<p class="no-indent">
I think both of these methods are not good practices. Especially, for my case, the way with @vercel/ncc is not feasible because some package uses <code>require</code>.
</p>
<p>The best way to handle this is to make GitHub cache and install all the dependencies for the user every time the action is run. This can be made possible by <a href="https://docs.github.com/en/actions/sharing-automations/creating-actions/creating-a-composite-action" target="_blank" rel="external">creating a composite action</a>. Here is a snippet in <code>action.yml</code>:</p>
<table class="rouge-table">
  <tbody>
    <tr>
      <td class="highlight language-yaml">
        <pre>
          <code>
            <span class="line line-1"><span class="na">runs</span><span class="pi">:</span>
</span>
            <span class="line line-2">  <span class="na">using</span><span class="pi">:</span> <span class="s">composite</span>
</span>
            <span class="line line-3">  <span class="na">steps</span><span class="pi">:</span>
</span>
            <span class="line line-4">    <span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s">Setup Node.js</span>
</span>
            <span class="line line-5">      <span class="na">uses</span><span class="pi">:</span> <span class="s">actions/setup-node@v4</span>
</span>
            <span class="line line-6">      <span class="na">with</span><span class="pi">:</span>
</span>
            <span class="line line-7">        <span class="na">node-version</span><span class="pi">:</span> <span class="s1">'</span><span class="s">20'</span>
</span>
            <span class="line line-8">
</span>
            <span class="line line-9">    <span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s">Get cache key and path</span>
</span>
            <span class="line line-10">      <span class="na">id</span><span class="pi">:</span> <span class="s">lock</span>
</span>
            <span class="line line-11">      <span class="na">run</span><span class="pi">:</span> <span class="pi">|</span>
</span>
            <span class="line line-12">        <span class="s">cd $GITHUB_ACTION_PATH</span>
</span>
            <span class="line line-13">        <span class="s">node &lt;&lt;'JAVASCRIPT'</span>
</span>
            <span class="line line-14">          <span class="s">const fs = require('fs');</span>
</span>
            <span class="line line-15">          <span class="s">const os = require('os');</span>
</span>
            <span class="line line-16">          <span class="s">const sha256 = require('crypto').createHash('sha256');</span>
</span>
            <span class="line line-17">          <span class="s">const hash = sha256.update(fs.readFileSync('package-lock.json')).digest('hex');</span>
</span>
            <span class="line line-18">          <span class="s">fs.appendFileSync(process.env.GITHUB_OUTPUT, `key=${os.platform()}-${os.arch()}-grs-modules-${hash}\n`);</span>
</span>
            <span class="line line-19">        <span class="s">JAVASCRIPT</span>
</span>
            <span class="line line-20">        <span class="s">modules=$(pwd)/node_modules</span>
</span>
            <span class="line line-21">        <span class="s">command -v cygpath &amp;&gt; /dev/null &amp;&amp; modules=$(cygpath -w $modules)</span>
</span>
            <span class="line line-22">        <span class="s">echo "modules=$modules" &gt;&gt; $GITHUB_OUTPUT</span>
</span>
            <span class="line line-23">        <span class="s">cat $GITHUB_OUTPUT</span>
</span>
            <span class="line line-24">        <span class="s">cd $GITHUB_WORKSPACE</span>
</span>
            <span class="line line-25">      <span class="na">shell</span><span class="pi">:</span> <span class="s">bash</span>
</span>
            <span class="line line-26">
</span>
            <span class="line line-27">    <span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s">Restore cache</span>
</span>
            <span class="line line-28">      <span class="na">uses</span><span class="pi">:</span> <span class="s">actions/cache/restore@v4</span>
</span>
            <span class="line line-29">      <span class="na">id</span><span class="pi">:</span> <span class="s">cache-restore</span>
</span>
            <span class="line line-30">      <span class="na">with</span><span class="pi">:</span>
</span>
            <span class="line line-31">        <span class="na">path</span><span class="pi">:</span> <span class="s">${{ steps.lock.outputs.modules }}</span>
</span>
            <span class="line line-32">        <span class="na">key</span><span class="pi">:</span> <span class="s">${{ steps.lock.outputs.key }}</span>
</span>
            <span class="line line-33">
</span>
            <span class="line line-34">    <span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s">CI</span>
</span>
            <span class="line line-35">      <span class="na">if</span><span class="pi">:</span> <span class="s">steps.cache-restore.outputs.cache-hit != 'true'</span>
</span>
            <span class="line line-36">      <span class="na">run</span><span class="pi">:</span> <span class="pi">|</span>
</span>
            <span class="line line-37">        <span class="s">cd $GITHUB_ACTION_PATH</span>
</span>
            <span class="line line-38">        <span class="s">npm ci</span>
</span>
            <span class="line line-39">        <span class="s">cd $GITHUB_WORKSPACE</span>
</span>
            <span class="line line-40">      <span class="na">shell</span><span class="pi">:</span> <span class="s">bash</span>
</span>
            <span class="line line-41">
</span>
            <span class="line line-42">    <span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s">Save cache</span>
</span>
            <span class="line line-43">      <span class="na">if</span><span class="pi">:</span> <span class="s">steps.cache-restore.outputs.cache-hit != 'true'</span>
</span>
            <span class="line line-44">      <span class="na">uses</span><span class="pi">:</span> <span class="s">actions/cache/save@v4</span>
</span>
            <span class="line line-45">      <span class="na">with</span><span class="pi">:</span>
</span>
            <span class="line line-46">        <span class="na">path</span><span class="pi">:</span> <span class="s">${{ steps.lock.outputs.modules }}</span>
</span>
            <span class="line line-47">        <span class="na">key</span><span class="pi">:</span> <span class="s">${{ steps.lock.outputs.key }}</span>
</span>
            <span class="line line-48">
</span>
            <span class="line line-49">    <span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s">Run</span>
</span>
            <span class="line line-50">      <span class="na">run</span><span class="pi">:</span> <span class="s">node $GITHUB_ACTION_PATH/index.js</span>
</span>
            <span class="line line-51">      <span class="na">shell</span><span class="pi">:</span> <span class="s">bash</span>
</span>
          </code>
        </pre>
      </td>
    </tr>
  </tbody>
</table>
<p>I manually use <code>actions/cache</code> to cache the <code>node_modules</code> directory although <code>actions/setup-node</code> has caching functionality. This is because it <a href="https://github.com/actions/setup-node/issues/819" target="_blank" rel="external">is not good yet</a>. Also, because <code>github.action_path</code> ends with <code>/./</code>, it can cause some problem due to the relative pathing. My workflow here works around those problems.</p>
<p>The hash in the cache key is calculated using JavaScript because there is no <code>sha256sum</code> command on macOS and Ubuntu runners.</p>]]></content><author><name>UlyssesZhan</name><email>ulysseszhan@gmail.com</email></author><category term="guide" /><category term="javascript" /><category term="github" /><summary type="html"><![CDATA[I was creating my first GitHub Action. According to the official documentation, I should commit the <code>node_modules</code> to the repo or generate a script that bundles the whole <code>node_modules</code> if I want to create a JavaScript action. I think this is not good practice, so I try to find another way: manually managing the caches for the dependencies in <code>node_modules</code>.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://ulysseszh.github.io/assets/images/covers/2024-11-15-gh-action-modules.png" /><media:content medium="image" url="https://ulysseszh.github.io/assets/images/covers/2024-11-15-gh-action-modules.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html"><![CDATA[Simulating a mechanical system using rpg_core.js]]></title><link href="https://ulysseszh.github.io/physics/2020/05/14/simulation-rpgmv.html" rel="alternate" type="text/html" title="Simulating a mechanical system using rpg_core.js" /><published>2020-05-13T09:57:39-07:00</published><updated>2020-05-13T09:57:39-07:00</updated><id>https://ulysseszh.github.io/physics/2020/05/14/simulation-rpgmv</id><content type="html" xml:base="https://ulysseszh.github.io/physics/2020/05/14/simulation-rpgmv.html"><![CDATA[<p>This post is the continuation of <a href="/physics/2020/04/28/simulation-rgss.html">the last post</a>.</p>
<p>If you visit <a href="/rpg/mechsimul/">the page</a> I have just created, you may find the simulation of a mechanical system.</p>
<figure>
<img src="/assets/images/figures/2020-05-14-simulation-rpgmv/rpgmv_simul.png" alt="Result of simulation"/>

</figure>
<p>It is currently <span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mi mathvariant="script">H</mi><mo>=</mo><msubsup><mi>p</mi><mn>1</mn><mn>2</mn></msubsup><mo>+</mo><msubsup><mi>p</mi><mn>2</mn><mn>2</mn></msubsup><mo>−</mo><mi>cos</mi><mo>⁡</mo><msub><mi>q</mi><mn>1</mn></msub><mo>−</mo><mi>cos</mi><mo>⁡</mo><msub><mi>q</mi><mn>2</mn></msub><mo>−</mo><mi>cos</mi><mo>⁡</mo><mtext> ⁣</mtext><mrow><mo fence="true">(</mo><msub><mi>q</mi><mn>1</mn></msub><mo>−</mo><msub><mi>q</mi><mn>2</mn></msub><mo fence="true">)</mo></mrow></mrow><annotation encoding="application/x-tex">
    \mathcal H=p_1^2+p_2^2-\cos q_1-\cos q_2-
    \cos\!\left(q_1-q_2\right)
</annotation></semantics></math></span></span></span> depicting two pendulum coupled with a spring (with <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>l</mi><mn>1</mn></msub><mo>=</mo><msub><mi>l</mi><mn>2</mn></msub></mrow><annotation encoding="application/x-tex">l_1=l_2</annotation></semantics></math></span></span> and <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>m</mi><mn>1</mn></msub><mo>=</mo><msub><mi>m</mi><mn>2</mn></msub></mrow><annotation encoding="application/x-tex">m_1=m_2</annotation></semantics></math></span></span>, and the original length of the spring is zero, and the two hanging points overlap),</p>
<figure>
<img src="/assets/images/figures/2020-05-14-simulation-rpgmv/spring_coupled_pendulum.png" class="dark-adaptive" alt="Spring-coupled pendulums"/>

</figure>
<p class="no-indent">
which is a classical example of non-linearly coupled system.
</p>
<p>The pattern of the oscillation can be analyzed using discrete Fourier transformation, whose result can be found by clicking the buttons in the up-left corner (after the simulator has detected a period).</p>
<figure>
<img src="/assets/images/figures/2020-05-14-simulation-rpgmv/rpgmv_simul_fft.png" alt="Result of DFT"/>

</figure>
<p class="no-indent">
Hitting the space bar can make the simulation pause.
</p>
<p>If you want to use it to simulate other mechanical systems, you can study <a href="/rpg/mechsimul/js/mechsimul.js">the codes</a> I wrote and write your own codes in the console.</p>
<p>By the way, the <a href="https://github.com/UlyssesZh/OpenRGSS/" target="_blank" rel="external">OpenRGSS</a> version of the simulator is open-source <a href="https://github.com/UlyssesZh/mechsimul/" target="_blank" rel="external">here</a>. Please star the repo if you like it.</p>]]></content><author><name>UlyssesZhan</name><email>ulysseszhan@gmail.com</email></author><category term="physics" /><category term="javascript" /><category term="rgss" /><category term="hamiltonian" /><category term="calculus" /><category term="ode" /><category term="web" /><category term="fourier transform" /><summary type="html"><![CDATA[Continuing my last work of simulating a mechanical system using RGSS3, I made a new version using rpg_core.js, the game scripting system shipped with RPG Maker MV. This version is live <a href="/rpg/mechsimul">on web</a>!]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://ulysseszh.github.io/assets/images/covers/2020-05-14-simulation-rpgmv.png" /><media:content medium="image" url="https://ulysseszh.github.io/assets/images/covers/2020-05-14-simulation-rpgmv.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html"><![CDATA[The structure of a basic RM game]]></title><link href="https://ulysseszh.github.io/programming/2020/04/08/basic-rm-game.html" rel="alternate" type="text/html" title="The structure of a basic RM game" /><published>2020-04-07T18:28:05-07:00</published><updated>2020-04-07T18:28:05-07:00</updated><id>https://ulysseszh.github.io/programming/2020/04/08/basic-rm-game</id><content type="html" xml:base="https://ulysseszh.github.io/programming/2020/04/08/basic-rm-game.html"><![CDATA[<p><a href="https://tkool.jp/" target="_blank" rel="external">RPG Maker (RM)</a> is a tool for making games.</p>
<p>I only have experience in using RPG Maker XP, RPG Maker VX, RPG Maker VX Ace, and RPG Maker MV.</p>
<p>Games made by using RM are based on</p>
<table>
<thead>
<tr>
<th>XP</th>
<th>VX</th>
<th>VA</th>
<th>MV</th>
</tr>
</thead>
<tbody>
<tr>
<td>RGSS</td>
<td>RGSS2</td>
<td>RGSS3</td>
<td>rpg_core.js</td>
</tr>
</tbody>
</table>
<p>In most cases, when I say RGSS, I mean RGSS, RGSS2, and RGSS3. RGSS is in Ruby and rpg_core.js is in Javascript.</p>
<p>The scripts of a basic RGSS game look like</p>
<table class="rouge-table">
  <tbody>
    <tr>
      <td class="highlight language-ruby">
        <pre>
          <code>
            <span class="line line-1"><span class="k">def</span> <span class="nf">start</span>
</span>
            <span class="line line-2">	<span class="c1"># some codes</span>
</span>
            <span class="line line-3"><span class="k">end</span>
</span>
            <span class="line line-4"><span class="k">def</span> <span class="nf">update</span>
</span>
            <span class="line line-5">	<span class="c1"># some codes</span>
</span>
            <span class="line line-6"><span class="k">end</span>
</span>
            <span class="line line-7">
</span>
            <span class="line line-8"><span class="n">start</span>
</span>
            <span class="line line-9"><span class="kp">loop</span> <span class="k">do</span>
</span>
            <span class="line line-10">	<span class="n">update</span>
</span>
            <span class="line line-11">	<span class="no">Input</span><span class="p">.</span><span class="nf">update</span>
</span>
            <span class="line line-12">	<span class="no">Graphics</span><span class="p">.</span><span class="nf">update</span>
</span>
            <span class="line line-13"><span class="k">end</span>
</span>
          </code>
        </pre>
      </td>
    </tr>
  </tbody>
</table>
<p>The scripts of a basic rpg_core.js game look like</p>
<table class="rouge-table">
  <tbody>
    <tr>
      <td class="highlight language-javascript">
        <pre>
          <code>
            <span class="line line-1"><span class="kd">function</span> <span class="nf">start</span><span class="p">()</span> <span class="p">{</span>
</span>
            <span class="line line-2">	<span class="c1">// some codes</span>
</span>
            <span class="line line-3"><span class="p">}</span>
</span>
            <span class="line line-4"><span class="kd">function</span> <span class="nf">update</span><span class="p">()</span> <span class="p">{</span>
</span>
            <span class="line line-5">	<span class="c1">// some codes</span>
</span>
            <span class="line line-6"><span class="p">}</span>
</span>
            <span class="line line-7">
</span>
            <span class="line line-8"><span class="nx">Graphics</span><span class="p">.</span><span class="nf">initialize</span><span class="p">(</span><span class="mi">816</span><span class="p">,</span> <span class="mi">624</span><span class="p">,</span> <span class="dl">'</span><span class="s1">webgl</span><span class="dl">'</span><span class="p">);</span>
</span>
            <span class="line line-9"><span class="nx">Graphics</span><span class="p">.</span><span class="nx">boxWidth</span> <span class="o">=</span> <span class="mi">816</span><span class="p">;</span>
</span>
            <span class="line line-10"><span class="nx">Graphics</span><span class="p">.</span><span class="nx">boxHeight</span> <span class="o">=</span> <span class="mi">624</span><span class="p">;</span>
</span>
            <span class="line line-11"><span class="nx">WebAudio</span><span class="p">.</span><span class="nf">initialize</span><span class="p">(</span><span class="kc">false</span><span class="p">);</span>
</span>
            <span class="line line-12"><span class="nx">Input</span><span class="p">.</span><span class="nf">initialize</span><span class="p">();</span>
</span>
            <span class="line line-13"><span class="nx">TouchInput</span><span class="p">.</span><span class="nf">initialize</span><span class="p">();</span>
</span>
            <span class="line line-14"><span class="kd">var</span> <span class="nx">deltaTime</span> <span class="o">=</span> <span class="mf">1.0</span> <span class="o">/</span> <span class="mf">60.0</span><span class="p">;</span>
</span>
            <span class="line line-15"><span class="kd">var</span> <span class="nx">accumulator</span> <span class="o">=</span> <span class="mf">0.0</span><span class="p">;</span>
</span>
            <span class="line line-16"><span class="kd">var</span> <span class="nx">currentTime</span><span class="p">;</span>
</span>
            <span class="line line-17"><span class="nb">window</span><span class="p">.</span><span class="nx">scene</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Stage</span><span class="p">();</span>
</span>
            <span class="line line-18"><span class="nf">start</span><span class="p">();</span>
</span>
            <span class="line line-19"><span class="kd">function</span> <span class="nf">performUpdate</span><span class="p">()</span> <span class="p">{</span>
</span>
            <span class="line line-20">	<span class="nx">Graphics</span><span class="p">.</span><span class="nf">tickStart</span><span class="p">();</span>
</span>
            <span class="line line-21">	<span class="kd">var</span> <span class="nx">newTime</span> <span class="o">=</span> <span class="nx">performance</span><span class="p">.</span><span class="nf">now</span><span class="p">();</span>
</span>
            <span class="line line-22">	<span class="k">if </span><span class="p">(</span><span class="nx">currentTime</span> <span class="o">===</span> <span class="kc">undefined</span><span class="p">)</span> <span class="nx">currentTime</span> <span class="o">=</span> <span class="nx">newTime</span><span class="p">;</span>
</span>
            <span class="line line-23">	<span class="kd">var</span> <span class="nx">fTime</span> <span class="o">=</span> <span class="p">((</span><span class="nx">newTime</span> <span class="o">-</span> <span class="nx">currentTime</span><span class="p">)</span> <span class="o">/</span> <span class="mi">1000</span><span class="p">).</span><span class="nf">clamp</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mf">0.25</span><span class="p">);</span>
</span>
            <span class="line line-24">	<span class="nx">currentTime</span> <span class="o">=</span> <span class="nx">newTime</span><span class="p">;</span>
</span>
            <span class="line line-25">	<span class="nx">accumulator</span> <span class="o">+=</span> <span class="nx">fTime</span><span class="p">;</span>
</span>
            <span class="line line-26">	<span class="k">while </span><span class="p">(</span><span class="nx">accumulator</span> <span class="o">&gt;=</span> <span class="nx">deltaTime</span><span class="p">)</span> <span class="p">{</span>
</span>
            <span class="line line-27">		<span class="nx">Input</span><span class="p">.</span><span class="nf">update</span><span class="p">();</span>
</span>
            <span class="line line-28">		<span class="nx">TouchInput</span><span class="p">.</span><span class="nf">update</span><span class="p">();</span>
</span>
            <span class="line line-29">		<span class="nf">update</span><span class="p">();</span>
</span>
            <span class="line line-30">		<span class="nx">accumulator</span> <span class="o">-=</span> <span class="nx">deltaTime</span><span class="p">;</span>
</span>
            <span class="line line-31">	<span class="p">}</span>
</span>
            <span class="line line-32">	<span class="nx">Graphics</span><span class="p">.</span><span class="nf">render</span><span class="p">(</span><span class="nb">window</span><span class="p">.</span><span class="nx">scene</span><span class="p">);</span>
</span>
            <span class="line line-33">	<span class="nf">requestAnimationFrame</span><span class="p">(</span><span class="nx">performUpdate</span><span class="p">);</span>
</span>
            <span class="line line-34">	<span class="nx">Graphics</span><span class="p">.</span><span class="nf">tickEnd</span><span class="p">();</span>
</span>
            <span class="line line-35"><span class="p">}</span>
</span>
            <span class="line line-36"><span class="nf">performUpdate</span><span class="p">();</span>
</span>
          </code>
        </pre>
      </td>
    </tr>
  </tbody>
</table>
<p>There is a simple rpg_core.js game written by me which can be accessed <a href="/rpg/hello/">here</a>. You can look at its source code by using your browser.</p>
<p>RM also provides a lot of scripts serving as making RPG. There is a simple RPG built by me which can be accessed <a href="/rpg/test/">here</a>.</p>
<p>The source codes of RGSS are secret, but those of rpg_core.js are not a secret and can be seen at <a href="https://github.com/rpgtkoolmv/corescript/" target="_blank" rel="external">its GitHub repo</a>.</p>]]></content><author><name>UlyssesZhan</name><email>ulysseszhan@gmail.com</email></author><category term="programming" /><category term="ruby" /><category term="javascript" /><category term="rgss" /><summary type="html"><![CDATA[In this article, I present minimal examples of a RM game. They only illustrate the basic concepts of how a RM game is structured and what is the running logic of it.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://ulysseszh.github.io/assets/images/covers/2020-04-08-basic-rm-game.png" /><media:content medium="image" url="https://ulysseszh.github.io/assets/images/covers/2020-04-08-basic-rm-game.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry></feed>