Location>code7788 >text

Live the Dream: Realize Your Game Development Dreams with CloudBase

Popularity:789 ℃/2024-12-13 23:29:49

Recently I've noticed that AI products are emerging in new directions, especially with the innovative products launched by some of the tech giants. For example, today we're going to explore the Tencent Cloud-developedCloud Development CloudBaseIf you haven't heard the name before, you may remember another product launched by Tencent Cloud - thetweedCloudBase is the micro-build platform that incorporates AI capabilities. That's right, CloudBase is that micro-build platform that incorporates AI capabilities, which helps users build websites more efficiently and conveniently, especially for users who are unfamiliar with development, greatly reducing the technical threshold.

In the previous section, I gave a primer on the AI capabilities of cloud development, which mentioned the ability to generate a web page from a single sentence, and while I just skimmed over it at the time, today we might want to dive in a little deeper and see how itVisualize and develop AI capabilitiesJust how powerful!

Today we are going to discuss the topic of developing aGun games-inspired by the classic Crossfire. And why I chose to use the Tencent Cloud development platform todayCloudBase To realize this dream? Because, CloudBase is built onLowering the development threshold and increasing development efficiencyAs a promotional highlight, it provides a variety of tools and AI capabilities to help developers quickly realize their projects, and even some beginners who are not familiar with programming can easily get started. Therefore, today I decided to use this platform to fulfill a dream I had buried in my heart when I first graduated from university: to develop a game of my own.

Of course, time was limited and the project couldn't get too big, so we decided to leave 3D development out of the equation for the time being - after all, we're mainly developing for front-end PC pages, so that the game's presentation will be centered around the2DExpand. Although we are not going the 3D route, we will still strive to achieve a fulfilling gameplay experience in 2D graphics, adding some interesting interactive elements and innovative gameplay.

So, without further ado.The game development journey has officially begun

Visual Cloud Development

preliminary

We do not beat around the bush, directly into the subject. If you have not opened the Tencent cloud services, simply go to the Tencent cloud console, search for "cloud development" and follow the prompts to complete the opening can be, the whole process is simple and intuitive, very easy to get started. As this part of the content is more basic, no longer in the article to explain in detail. As shown in the figure:

image

After completing the necessary environmental preparations, we can directly click into the relevant page to start the subsequent operation. As shown in the figure:

image

After entering the environment, we directly select the "Visual Development" option to start building the AI-driven website.

image

Okay, all the preliminary preparations have been successfully completed, then we officially enter the theme - start building the gun game. It should be noted that during the building process, we will encounter many problems and challenges, involving the implementation and fixing of a series of features such as picture sliding, collimator targeting, page optimization and so on. Although these details are important, if we list and discuss them one by one, the content of the article will be too long and cumbersome.

Therefore, the core purpose of this post is to teach you how to use building techniques to solve these problems and help you get your game built efficiently, rather than focusing on each specific minor problem.

Start building game

By default, the cloud development platform contains several intelligent body assistants, users can call the corresponding assistant function by @ tag according to the actual demand. Please refer to the following figure for the specific operation method:

image

We will directly use the AI generation component provided by default in order to quickly test its effect and performance performance. As shown in the figure:

image

If you're not completely satisfied with the results of your current page, you can always continue to ask questions and let the AI assistant help you beautify and adjust the page. However, it's worth noting that while AI can be of great help in terms of optimization and design, it can't completely replace your work. In fact, it can replace up to about 70% of your workload, which is already a pretty good performance.

Keep in mind that AI writes code from scratch when generating content, rather than accepting and updating it line by line, so the results may vary each time. When you see a page that is close to ideal, you can simply create the application and make subsequent optimizations and adjustments to ensure that the final result meets your needs. The process is shown below:

image

library

picture material

When you are in the process of creating a website, you usually need to use a large number of images, charts and various other material resources, before you start website development, you can upload these materials to the platform or server in advance, so as to follow up with more efficient page design and content integration. The following figure shows the specific steps or examples of this operation:

image

However, at the moment, you still can't select these images directly when building your website. Therefore, your main task is to copy the image links here. Of course, it would be better if you have your own image bed, because then you can not only use your own image resources directly, but also update the image content at any time. It is important to note that the gallery provided here does not allow for image update operations, only deletion or re-uploading. Therefore, this point may become a stuck point in your operation.

Music/video clips

At the moment, the cloud development material library does not support adding music or video files for the time being, but if you have such needs, you can completely solve them in other ways. Specifically, you can choose to use your own server and expose the files through it. It's not complicated, and I've gone ahead and configured it for you. All you need to do is install and configure a Nginx service on your own server and prepare a special folder for the footage files.

This way, you can easily provide audio or video files to your cloud development library by enabling file access and management through Nginx.

Step 1: Install nginx

Here I use the Pagoda panel that comes with Tencent Cloud Lightweight Server, you just need to quickly complete the installation through the one-click installation function, the installation process is very simple, the specific steps are shown in the figure:

image

Step 2: Prepare the clip folder

We just need to directly create an empty folder as a directory to store material files, convenient for subsequent material management and operation. As shown in the figure:

image

Step 3: Configure Nginx Reverse Generation

The last step, we directly configure the nginx proxy, note that here you need to solve the cross-domain problem, otherwise Tencent cloud can not directly access our server. Configuration is as follows:

# Static file services(photograph、audio frequency)
location /media/ {
   alias /data/disk/media/; # Directory where media files are stored
  try_files $uri $uri/ =404; # Returns if the file does not exist404

  # CORS configure
  add_header Access-Control-Allow-Origin *; # Allow access to all domains
  add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS'; # permissible HTTP methodologies
  add_header Access-Control-Allow-Headers 'Origin, X-Requested-With, Content-Type, Accept, Authorization'; # permissiblerequesting头
  add_header Access-Control-Max-Age 3600; # Cache time for preflight requests,In seconds.

  # deal with OPTIONS requesting(用于预检requesting)
  if ($request_method = 'OPTIONS') {
      add_header Access-Control-Allow-Origin *;
      add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS';
      add_header Access-Control-Allow-Headers 'Origin, X-Requested-With, Content-Type, Accept, Authorization';
      add_header Access-Control-Max-Age 3600;
      return 204; # 对预检requesting返回 204 No Content
  }

  access_log /www/wwwlogs/;
}

Please paste this part of the code directly into the server module you want to listen to. This way we can test it directly in the browser to see if it works. As you can see in the picture:

image

Okay, after some organizing and preparation, we basically have all of our footage ready to go. Next, our focus will turn to how to use these materials effectively and maximize their potential.

Of course, in addition to those complex solutions, I'd like to share with you next some simple solutions in cloud development that can fulfill the needs while remaining efficient and flexible.

cloud storage

Each package has its fixed amount of storage. For example, in the case of my Personal Development Edition, it provides approximately 2GB of storage, which is more than enough for most daily development needs. If you find that the storage space is not enough for your needs during actual use, don't worry. You can follow the previously mentioned steps to build additional storage solutions on your own to ensure that you can flexibly cope with growing data storage needs.

image

You can use it exactly as your own folder. However, it is important to note that the cloud storage platform does not allow the name of the folder or file to be changed. Therefore, before uploading a file, unless there is a special need, it is recommended to change the Chinese name of the folder or file to English or other characters. As shown in the picture:

image

All we need is this temporary link, after getting this link, you can use the related resources normally, the whole process is very simple and intuitive. In addition to providing the basic link function, Cloud Function also has a very important feature, that is, it supports cache settings and CDN acceleration, which means that it can significantly improve the speed and efficiency of file access, reduce latency and optimize the user experience. As shown in the figure:

image

How to use

For example, if we wish to add a music playback component to an existing interface, we can refer to the illustration shown below:

image

Therefore, we only need to enter the corresponding file path in the URL bar, and the system will automatically recognize and load the required resources. Please refer to the diagram below for the procedure:

image

If you have filled in the URL path correctly, but still cannot play the music properly, or encounter the error situation shown in the figure below, then it is most likely due to cross-domain issues. As shown in the figure:

image

Here's another thing to note in particular: if you want your music to play automatically (such as the background music I've set up), you have to make sure that the music player component is visible. If the player component is hidden or not shown, the music will not be able to play automatically, as shown here:

image

Using images is very easy, you can embed them in an image container or add them as a background. As shown in the picture, the method of operation is intuitive and flexible.

image

There are no more tips here about the material. Let's move on.

New page

Of course, our app doesn't just rely on a single page for its entire functionality. After all, for a shooting game, a single page design is far from enough. Our game page will consist of three main sections: first, the Web Introduction page, which is used to display the basic information and features of the game; next, the Map Selection page, where players can choose their favorite battle maps; and lastly, the Game Combat page, where the player enters the actual battle scenario.

Therefore, we can use AI technology to further optimize and generate these pages to ensure that each page has the best user experience and functionality, as shown below:

image

After the generation is complete, we can select the corresponding page here and make selective edits and adjustments as needed. As shown in the figure below:

image

How to import the original page

Here we have some problems. For example, if I already have a ready-made HTML page, how do I import it in? The current structure here is built completely from scratch, without any ready-made import function. So, what should I do in this situation? Actually, there is a solution here - the JSX module. As shown in the picture:

image

When using JSX to import an existing page, it is especially important to note that the target page must be an empty page and cannot contain any components. The reason for this is that JSX handles the creation and rendering of components automatically. If other components already exist in the target page, it may cause conflicts or affect the rendering effect. Therefore, to avoid unnecessary errors or confusion, make sure the target page is clean and blank when imported.

Next, we will demonstrate step-by-step how to import an existing page into JSX. To simplify the demonstration process, I'm using a raw HTML file here rather than a complex page that integrates various front-end frameworks.

Below is the content of the original HTML file:

image

When a page contains a lot of commonly used CSS, JavaScript, and a variety ofdiv When it comes to containers, if we choose to manually copy and paste them one by one into a new project, this approach is not only inefficient, but also wastes almost as much time as designing and building a whole new page from scratch. In this case, intelligent tools and AI assistants are especially important. For example, Tencent's Hybrid AI Assistant can significantly improve our development efficiency.

To do this, we only need to provide the AI with a reference example, similar to what is shown in the diagram, and the AI assistant will be able to intelligently analyze, extract and generate the required code structure. This not only saves a lot of time and energy, but also ensures the consistency and efficiency of the code, greatly improving the workflow and quality of development.

image

Next, you need to provide the full HTML code to the AI assistant, along with the corresponding JSX syntax examples. This will basically get you up and running. Be careful not to overload the page with too much content, as too much complexity can lead to errors during the import process. The result looks like the following:

image

As you can see, I'm not using multiple components here, just a simple JSX component. So, the question is, what should we do with our original JavaScript event handling and CSS styles? Actually, all of this is already implemented in JSX.

In this way, we can not only keep the original logic, but also embed JavaScript events and styles directly into the JSX code, making the whole component more compact and easy to manage. This is shown in the following figure:

image

click event

buttons

We can add all types of event responses to our components, not just limited to buttons. In fact, almost any component can be bound to event handlers, including text boxes, images, links, and even custom components. For example, a very common requirement is to add click events to buttons so that they can jump to a specified built-in page when clicked.

image

photograph

However, it is worth noting that in our map selection page, the user interaction is by clicking on the image to make a selection. Nonetheless, there is still a click event triggering mechanism for the image, as shown in the figure:

image

jump to a new page

I will briefly explain the part about page jumping, other functions are not covered for the time being. Normally, you can choose to do the page jump operation within this application in the following way:

image

For the use of external links, simply use the jump page function provided above to easily realize the jump operation.

JSX Components

This part of the work can be completely left to the AI assistant, after all, we have asked the AI assistant many times. On each query, the cloud development assistant will regenerate the JSX code according to our request, as shown below.

image

To avoid losing your current progress, if you are in a satisfactory situation, remember to press and hold theCTRL+S Shortcut keys to save the file. Doing so not only ensures that your work product is retained in a timely manner, but also makes it easy to roll back to the saved version of the source code if needed in the future. Below is a schematic of how rolling back to a historical version after saving works:

image

keystroke listener

Similarly, for more complex customizations and interactions, we can use JSX to write event listeners, such as key presses, in addition to regular JavaScript code. Although the official documentation mainly provides the implementation of mouse click events, in some specific scenarios, such as the need to exit the game by pressing the ESC key in my game, such needs cannot be satisfied by click events alone. Therefore, for these specific needs, we can write the corresponding key-listening logic directly in the JSX code. This is shown in the figure:

image

JSX Component Syntax

In the image above, you may have noticed that when I listen to theESC When the key is pressed, a method is triggered that directly displays a popup window. The popup is implemented using the built-in JSX component syntax, which has many varieties and features that make it easy to build interactive UI elements. For more detailed information on component usage and API documentation, see the following links:CloudBase Documentation - Tools API

There are a number of specific syntaxes, as shown here:

image

Each one has a specific example demo, just copy it.

Game View Source Code

Ok, here I will share my current implementation of the game's viewpoint. If you're interested, you can dive into the entire gameplay process, including the specific implementation of page rendering, sound processing, and gun-holding perspectives. Below is the relevant code showing how I programmatically implemented these features. I hope this can bring you some inspiration, if you have any questions, please feel free to discuss together!

import React, { useEffect, useRef, useState } from 'react';

export default function ImageDisplay(props) {
    const containerRef = useRef(null);
    const imageRef = useRef(null);
    const enemiesContainerRef = useRef(null);
    const [enemies, setEnemies] = useState([]);
    const [modalImage, setModalImage] = useState(null);  // New Status,Used to control pop-up images
    const audioRef = useRef(null); // Creating Audio References
    const audioRef2 = useRef(null); // Creating Audio References


    const enemyImages = [
        "/resources/2024-12/lowcode-2054301", 
        "/resources/2024-12/lowcode-2054312"
    ];

    // Mouse following effect
    useEffect(() => {
        const container = ;
        const image = ;
        const enemiesContainer = ;

        let offsetX = 0;
        let offsetY = 0;

        const handleMouseMove = (e) => {
            const containerRect = ();
            const mouseX =  - ;
            const mouseY =  - ;
            const centerX =  / 2;
            const centerY =  / 2;
            offsetX = (centerX - mouseX) * 0.05;
            offsetY = (centerY - mouseY) * 0.05;

             = `translate(-50%, -50%) translate(${offsetX}px, ${offsetY}px)`;
             = `translate(-50%, -50%) translate(${offsetX}px, ${offsetY}px)`;
        };

        const handleMouseLeave = () => {
             = 'translate(-50%, -50%)';
             = 'translate(-50%, -50%)';
        };

        ('mousemove', handleMouseMove);
        ('mouseleave', handleMouseLeave);

        // Clear event listeners
        return () => {
            ('mousemove', handleMouseMove);
            ('mouseleave', handleMouseLeave);
        };
    }, []);

    // Add Enemy
    const addEnemy = () => {
        const randomEnemyImage = enemyImages[(() * )];
        const containerRect = ();
        const imageRect = ();

        // Get Container Center90%Size of the area
        const centerWidth =  * 0.9;
        const centerHeight =  * 0.9;

        // Calculate the range of placeable enemies,bring to light90%regional
        const maxX = centerWidth - 50; // Subtract the width of the enemy icon
        const maxY = centerHeight - 50; // Subtract the height of the enemy icon
        const minX = ( - centerWidth) / 2;
        const minY = ( - centerHeight) / 2;

        // Generate Random Positions,cap90%regional
        const randomX = minX + () * maxX;
        const randomY = minY + () * maxY;

        const newEnemy = {
            id: (),
            image: randomEnemyImage,
            x: randomX,
            y: randomY
        };

        setEnemies((prevEnemies) => [...prevEnemies, newEnemy]);

        setTimeout(() => {
            setEnemies((prevEnemies) => (enemy =>  !== ));
        }, 5000);
    };

    useEffect(() => {
        const intervalId = setInterval(addEnemy, 3000);
        return () => clearInterval(intervalId);
    }, []);

    // Clicking on an enemy event handler
    const handleEnemyClick = (enemyId, enemyImage) => {
        // Remove Enemy
        setEnemies((prevEnemies) => (enemy =>  !== enemyId));

        // Setting up a popup image and displaying it 1 Disappears automatically after a second
        setModalImage('/resources/2024-12/lowcode-2054324');
        // Reset the audio playback progress to0
        if () {
             = 0;  // Reset audio playback progress
             = 1;        // Setting the volume to maximum
            ().catch((error) => {
                ("Audio playback failure", error);
            });
        }

        setTimeout(() => {
            setModalImage(null);  // 1 Clear pop-up image after seconds
        }, 1000);
    };

    // monitorESCkeystrokes
    useEffect(() => {
        const handleKeyDown = (e) => {
            if ( === 'Escape') {
                // Trigger modal popups
                $({
                    title: 'Game Tips',
                    content: 'It's a modal popup.',
                    success(res) {
                        if () {
                            ('The user clicks OK');
                        } else if () {
                            ('User clicks to cancel');
                        }
                    },
                });
            }
        };

        ('keydown', handleKeyDown);

        // Clear event listeners
        return () => {
            ('keydown', handleKeyDown);
        };
    }, []);

    // Play sound effects with each mouse click
    useEffect(() => {
    const handleMouseClick = () => {
        // Reset the audio playback progress to0
        if () {
             = 0;  // Reset audio playback progress
             = 1;        // Setting the volume to maximum
            ().catch((error) => {
                ("Audio playback failure", error);
            });
        }
    };

    // existdocument上monitor点击事件
    ('click', handleMouseClick);

    // Clear event listeners
    return () => {
        ('click', handleMouseClick);
    };
    }, []);

    return (
        <div
            ref={containerRef}
            style={{
                position: 'fixed',  // utilizationfixedbring it up to full screen
                top: 0,
                left: 0,
                width: '100vw',
                height: '100vh',
                overflow: 'hidden',  // Disable scrollbars
                display: 'flex',
                justifyContent: 'center',
                alignItems: 'center',
                backgroundColor: '#f0f0f0',
                margin: 0,  // Make sure there are no extra margins
                padding: 0,  // Make sure there are no extra inside margins
                boxSizing: 'border-box',  // Ensure element size includes margins and inner margins
                cursor: 'url(/resources/2024-12/lowcode-2051938), crosshair', // Setting up a custom cursor
            }}
        >
            <div
                style={{
                    position: 'absolute',
                    top: '50%',
                    left: '50%',
                    transform: 'translate(-50%, -50%)',
                    width: '120%',
                    height: '120%',
                    overflow: 'visible',
                }}
            >
                <img
                    ref={imageRef}
                    src="/resources/2024-12/lowcode-2051969"
                    alt="Image"
                    style={{
                        position: 'absolute',
                        top: '50%',
                        left: '50%',
                        transform: 'translate(-50%, -50%)',
                        width: '100%',
                        height: '100%',
                        transition: 'transform 0.1s ease',
                        zIndex: -1, // Background image
                    }}
                />
            </div>

            <div
                ref={enemiesContainerRef}
                style={{
                    position: 'absolute',
                    top: '50%',
                    left: '50%',
                    transform: 'translate(-50%, -50%)',
                    width: '100%',
                    height: '100%',
                    overflow: 'visible',
                }}
            >
                {((enemy) => (
                    <div
                        key={}
                        style={{
                            position: 'absolute',
                            width: '80px',
                            height: '80px',
                            backgroundImage: `url(${})`,
                            backgroundSize: 'cover',
                            left: `${}px`,
                            top: `${}px`,
                            cursor: 'url(/resources/2024-12/lowcode-2051938), crosshair',  // Maintaining the collimator cursor
                            pointerEvents: 'auto',  // Ensure that the enemy icon receives events
                        }}
                        onClick={() => handleEnemyClick(, )} // Click on the enemy
                    />
                ))}
            </div>

            {/* Pop-up picture(Click on the enemy时展示) */}
            {modalImage && (
                <img
                    src={modalImage}
                    alt="Modal Image"
                    style={{
                        position: 'absolute',
                        top: '85%',
                        left: '50%',
                        transform: 'translate(-50%, -85%)',
                        width: '70px',
                        height: '70px',
                        zIndex: 1000, // 确保弹出的图片exist最上层
                    }}
                />
            )}
            {/* Bottom centered image */}
            <img
                src="/resources/2024-12/lowcode-2054553"
                alt="Bottom Center Image"
                style={{
                    position: 'absolute',
                    bottom: '1px',  // 固定exist底部,Distance to bottom20px
                    left: '60%',
                    transform: 'translateX(-60%)',  // center
                    width: '350px',  // Fixed width of50px
                    height: '350px',  // Fixed height of50px
                    zIndex: 1,  // Make sure it's on top
                }}
            />
            {/* Sound Files,audio element */}
            <audio ref={audioRef} src="https://domain name/media/shut.mp3" />
            {/* Sound Files,audio element */}
            <audio ref={audioRef2} src="https://domain name/media/laught.mp3" />
        </div>
    );
}

All of them are ready to run except for the last two audio files you need to replace with your own.

game effect

The exciting moment has finally arrived, my game is finally finished! After countless hours of design, development and tweaking, this moment has finally arrived.

Experience Address:/7h1hex26/preview/?envType=preview

I recorded a video to better demonstrate the background sound effects, page jumps, and other interactive elements of the game.

/developer/video/81621

summarize

As the journey of game development draws to a close, we can't help but marvel at the power and convenience of Tencent Cloud's CloudBase platform for development. From the initial page construction to the implementation of complex game perspectives, CloudBase, with its AI-driven visualization development tools, made the entire development process exceptionally efficient. It not only lowers the technical threshold, but also greatly improves the development efficiency, making it possible for even beginners to quickly get started and realize their creativity.

During the process, I experienced every step from material preparation to page construction, and felt the advantages of CloudBase in simplifying the development process and providing rich components and tools. Whether it is uploading and managing image materials or integrating music and video materials, CloudBase provides an intuitive interface and flexible solutions. It is especially worth mentioning that through JSX components and event listeners, we can easily realize complex interaction logic, such as key listening and page jumping, which greatly enriches the playability and user experience of the game.

With CloudBase, we not only realized a simple 2D shooter game, but more importantly, we mastered a new way of development, which combines AI capabilities with cloud services, providing unlimited possibilities for future project development.

Finally, I hope that this article will inspire more developers to join CloudBase and use this platform to realize their creativity and dreams.


I'm Rain, a Java server-side coder, studying the mysteries of AI technology. I love technical communication and sharing, and I am passionate about open source community. I am also a Tencent Cloud Creative Star, Ali Cloud Expert Blogger, Huawei Cloud Enjoyment Expert, and Nuggets Excellent Author.

💡 I won't be shy about sharing my personal explorations and experiences on the technology path in the hope that I can bring some inspiration and help to your learning and growth.

🌟 Welcome to the effortless drizzle! 🌟