jquery创建a_如何使用jQuery创建游戏

jquery创建a

How to create a game using jQuery
How to create a game using jQuery

How to create a game using jQuery Today we are making a simple puzzle game called “Fifteen”. The purpose of the game is to slide 15 square blocks around to form an image. The goal of this tutorial is to look at this simple browser-based game and explain how it was made line by line. It’s a great way to learn jQuery. For this tutorial, We will use a 2D image square-sliding game I created last week and I will go over each line of code to demonstrate the train of thought. I really do believe that breaking this game up into explanations on per-line basis will help you understand how to use jQuery in your own projects.

如何使用jQuery创建游戏今天,我们正在制作一个名为“十五”的简单益智游戏。 游戏的目的是在周围滑动15个正方形块以形成图像。 本教程的目的是研究这个简单的基于浏览器的游戏,并逐行说明它是如何制作的。 这是学习jQuery的好方法。 在本教程中,我们将使用我上周创建的2D图像正方形滑动游戏,并且将遍历每行代码以演示思路。 我确实相信,将游戏逐行分解为各种解释将有助于您了解如何在自己的项目中使用jQuery。

现场演示

将游戏创建为jQuery插件 (Creating a Game as a jQuery Plugin)

A jQuery plugin is a perfect way to create image slideshows, custom user interface controls and of course browser-based games. We won’t just write JavaScript code here, we will create a jQuery plugin.

jQuery插件是创建图像幻灯片,自定义用户界面控件以及基于浏览器的游戏的理想方式。 我们不仅在这里编写JavaScript代码,还将创建一个jQuery插件。

A plugin is nothing more than our own custom jQuery method. You know how we have jQuery’s methods .css() and .animate()? Well, jQuery gives us the ability to extend its own functionality with custom methods that we create ourselves. Like the existing jQuery methods, we can apply the method we will create to a jQuery selector.[1]

插件只不过是我们自己的自定义jQuery方法。 您知道我们如何使用jQuery的方法。 css ()和。 动画 ()? 好的,jQuery使我们能够使用我们自己创建的自定义方法扩展其自身功能。 像现有的jQuery方法一样,我们可以将要创建的方法应用于jQuery选择器。 [1]

Well, the game is called Fifteen, and we want to make our game “embeddable” inside an arbitrary HTML element like <div id="game_object">here</div> so we can move it around anywhere on the page (Different sites have different layouts, wouldn’t you like to have the ability to embed your jQuery game/plugin into an arbitrary DIV element on any site?)

好吧,该游戏称为《十五》,我们希望将游戏“嵌入”到任意HTML元素(如<div id =“ game_object”>此处</ div>)中,以便我们可以在页面上的任意位置(不同站点)移动它。具有不同的布局,您是否不希望能够将jQuery游戏/插件嵌入到任何网站上的任意DIV元素中?)

Let’s get started with the jQuery code.

让我们开始使用jQuery代码。

We will actually create our own jQuery method and call it .fifteen(). Therefore, in order to launch the game inside an HTML element with id “#game_object” we will call this command:

实际上,我们将创建自己的jQuery方法并将其称为.fifteen() 。 因此,为了在ID为“ #game_object”HTML元素中启动游戏,我们将调用以下命令:


$("#game_object").fifteen(175);

$("#game_object").fifteen(175);

This will create and attach the game board to the div whose id is “game_object.” Also, each square will become 175 by 175 pixels in width and height based on the only passed parameter.

这将创建游戏板并将其附加到ID为“ game_object”的div上。 同样,基于唯一传递的参数,每个正方形的宽度和高度将变为175 x 175像素。

In this tutorial I used the image of a kitty. You can replace it with any image you want.

在本教程中,我使用了小猫的形象。 您可以将其替换为所需的任何图像。

Executing a custom method as shown in the code above will pass the selector string “#game_object” to our plugin function which grabs the DIV. Inside our custom method, we can refer to that selector/element using the this keyword. And we can also enable jQuery methods on it by passing it to the new jQuery object like so: $(this); — inside the extended function we will create.

执行上面代码中所示的自定义方法,会将选择器字符串“ #game_object”传递给我们的插件函数,该插件函数捕获DIV。 在我们的自定义方法中,我们可以使用this关键字引用选择器/元素。 我们还可以通过将其传递给新的jQuery对象来启用jQuery方法,如下所示:$( this ); —在扩展函数中,我们将创建。

In order to create our own jQuery plugin we will use the $.fn.extend method.

为了创建我们自己的jQuery插件,我们将使用$ .fn.extend方法。

We can also refer to this as extending functionality of the jQuery library with our own methods. Let’s take a look:

我们也可以将其称为使用我们自己的方法扩展jQuery库的功能。 让我们来看看:


 $.fn.extend({
    fifteen: function (square_size) {
        // Game code goes here...
        // Example -- set the width of all DIVs to what was passed as square_size
        $("div").css({width: square_size});
        // The basics of the inner-workings of a plugin:
        var a = this;                // refers to the passed selector,
                                     // eg: $("#game_object")
        var b = $(this);             // same thing, but with jQuery methods enabled
        // Let's do something with the HTML element passed as the CSS selector
        this.style.color = "red";    // paint all text inside "#game_object" red
        $(this).css("color", "red"); // same exact thing, using jQuery method .css()
    }
});

 $.fn.extend({
    fifteen: function (square_size) {
        // Game code goes here...
        // Example -- set the width of all DIVs to what was passed as square_size
        $("div").css({width: square_size});
        // The basics of the inner-workings of a plugin:
        var a = this;                // refers to the passed selector,
                                     // eg: $("#game_object")
        var b = $(this);             // same thing, but with jQuery methods enabled
        // Let's do something with the HTML element passed as the CSS selector
        this.style.color = "red";    // paint all text inside "#game_object" red
        $(this).css("color", "red"); // same exact thing, using jQuery method .css()
    }
});

That’s it! This is the basic structure of any jQuery plugin.

而已! 这是任何jQuery插件的基本结构。

The code examples I use above are just examples that show how the basics work internally. But we will write an entire game within the scope of the function we called “fifteen”.

我上面使用的代码示例仅是说明基础知识如何在内部工作的示例。 但是我们将在我们称为“十五”的函数范围内编写整个游戏。

Within the scope of the plugin the this object refers to what was passed in the selector. Also, the square_size parameter is just a custom, arbitrary parameter passed to our game.

在插件范围内, 对象引用选择器中传递的内容。 另外,square_size参数只是传递给我们游戏的自定义任意参数。

We decide what the parameters should be, and if your game or plugin require more, simply define more parameters, as in:

我们确定参数应该是什么,如果您的游戏或插件需要更多参数,只需定义更多参数即可,如:

$.fn.extend( { fifteen: function(square_size, param2, param3, etc) { /*.. game code…*/ } } );

$ .fn.extend({ 十五 :函数(square_size,param2,param3等){ / * ..游戏代码…* / }});

Within the scope of your plugin you refer to parameters by the very same names.

在插件范围内,您可以使用完全相同的名称来引用参数。

In my case square_size is the only parameter. It defines the arbitrary size of the square in the game. I use 175 (as in 175 pixels in width and height). The grid is 16 by 16, but there are only 15 movable squares, because one is always empty. However, we still create all 16 DIVs, and just make one white. We do this in order to simulate the shadow effect on an empty square.

在我的情况下,square_size是唯一的参数。 它定义了游戏中正方形的任意大小。 我使用175(宽度和高度为175像素)。 网格为16 x 16,但只有15个可移动的正方形,因为一个始终为空。 但是,我们仍然创建所有16个DIV,并且只制作一个白色。 我们这样做是为了模拟在一个空的正方形上的阴影效果。

Before we get into the code, let’s take a look at the game’s construction as far as HTML goes. You will notice that there are 16 squares and each square is a separate DIV element:

在开始编写代码之前,我们先来看一下HTML的游戏构造。 您会注意到有16个正方形,每个正方形是一个单独的DIV元素:

game fifteen

比赛十五

The point of the game is to shuffle the image, one square at a time (by shifting it into the empty square, thus swapping locations) until the image is complete.

游戏的重点是一次将图像随机播放一个正方形(将其移动到空白正方形,从而交换位置),直到图像完整为止。

The white square is always empty. You are only allowed to shift squares that can physically be shifted into the empty spot, as if on a physical game board. This means only squares to the north, south, west and east of the empty square can be shifted. This test is performed within the stand-alone function I wrote and called Move() – it is separate from the plugin itself, it’s like a helper function.

白色正方形始终为空。 您只能移动可以物理移动到空白处的方块,就像在物理游戏板上一样。 这意味着只能向空白方块的北,南,西和东方移动。 该测试在我编写的独立函数Move()中执行 –它与插件本身是分开的,就像一个辅助函数。

Before I show you the code, I want to briefly talk about some common problems we will face while designing a plugin-based game.

在向您展示代码之前,我想简要介绍一下在设计基于插件的游戏时我们将面临的一些常见问题。

1.将插件嵌入到任意DIV(或其他HTML元素)中 (1. Embedding the Plugin Into Arbitrary DIVs (or other HTML elements))

Remember that when writing your plug-in it is wise to inject the HTML elements which are created as part of the game… into a parent DIV. The purpose of this is that your plug-in becomes embeddable into any arbitrary HTML element. Different websites have different layouts. So it’s important for our plug-in to be flexible. That it could be embedded into an arbitrary HTML element anywhere on the page. In this example I called that element:

请记住,编写插件时,明智的做法是将在游戏中创建HTML元素注入到父DIV中。 这样做的目的是使您的插件可嵌入到任意HTML元素中。 不同的网站具有不同的布局。 因此,我们的插件必须具有灵活性,这一点很重要。 可以将其嵌入到页面上任意位置的任意HTML元素中。 在此示例中,我将该元素称为:


<div id="game_object"></div>

<div id="game_object"></div>

Moving around this element will physically move the game around anywhere on the page.

移动此元素将使游戏实际在页面上的任何位置移动。

2.使用.append(html)方法将HTML注入空元素 (2. Injecting HTML into Empty Elements Using the .append(html) Method)

We leave <div id="game_object"></div> unpopulated with any game HTML. Why’s that? This is because the plugin itself will generate game’s HTML elements and insert them into the target DIV. No need to pre-type them “by hand.”

我们在<div id =“ game_object”> </ div>中保留未填充任何游戏HTML的内容。 为什么? 这是因为插件本身将生成游戏HTML元素并将其插入目标DIV中。 无需“手动”预先输入。

This is smart, because it keeps the parent element clean. But also, this example in particular allows us to explore the jQuery’s native .append(html) method. It literally appends new HTML at the end of a specified element. That is, you never even have to write HTML into the document itself, the .append() method injects HTML into the web page dynamically, you just specify the target element using a selector like:

这很聪明,因为它可以使父元素保持干净。 而且,此示例尤其允许我们探索jQuery的本机.append(html)方法。 它实际上将新HTML附加在指定元素的末尾。 也就是说,您甚至不必将HTML写入文档本身,.append()方法可将HTML动态注入网页,您只需使用选择器指定目标元素,例如:


$('#board').append("<div></div>"); // Add one div to the end of #board

$('#board').append("<div></div>"); // Add one div to the end of #board

3.使用:nth-​​child(index)代替ID或类 (3. Using :nth-child(index) Instead of IDs or Classes)

I think it’s worth mentioning that we can refer to DIVs inside, say, a parent DIV as children. This is really helpful. For example, let’s say we have 16 DIVs (children) stored inside one parent DIV:

我认为值得一提的是,我们可以将内部DIV称为 DIV。 这真的很有帮助。 例如,假设我们在一个父级DIV中存储了16个DIV(子级):


<div id="board"> <!-- This is called a "parent" element //-->
    <div></div>
    <div></div>
    <div></div>
        <!-- ... ok, imagine 16 DIVs here. These are the "children" of "#board" //-->
    <div></div>
    <div></div>
</div>

<div id="board"> <!-- This is called a "parent" element //-->
    <div></div>
    <div></div>
    <div></div>
        <!-- ... ok, imagine 16 DIVs here. These are the "children" of "#board" //-->
    <div></div>
    <div></div>
</div>

You don’t really need to assign 16 IDs to all 16 DIVs! jQuery takes care of that for us. For example, to refer to the 3rd DIV inside a parent DIV (in our game it’s #board,) instead, we can do something like this without ever assigning any classes or ids to any of the children:

您实际上并不需要为所有16个DIV分配16个ID! jQuery为我们解决了这一问题。 例如,要引用父DIV中的第三个DIV(在我们的游戏中为#board),我们可以执行以下操作,而无需为任何子代分配任何类或ID:


// Hide 3rd DIV in the list of children. No need to assign an id to each one!
$('#board').children('div:nth-child(3)').hide();

// Hide 3rd DIV in the list of children. No need to assign an id to each one!
$('#board').children('div:nth-child(3)').hide();

Notice we used the .children() method to grab all children of a parent (DIVs inside parent,) and then we also specified that we need a 3rd child using the literal selector :nth-child(n) where n is the index of the DIV we need. Note, however that this index doesn’t start with 0 like JavaScript arrays. It starts with index of 1. :nth-child(0) will not select anything.

请注意,我们使用.children()方法来获取父级的所有子级(父级中的DIV),然后我们还指定了我们需要使用文字选择器的第三个子级:nth-​​child(n),其中n是我们需要的DIV。 但是请注意,该索引并非像JavaScript数组那样以0开头。 它以索引1开始。:nth-​​child(0)将不选择任何内容。

Well, I think we are ready to start writing the code. Let’s get to it.

好吧,我认为我们已经准备好开始编写代码。 让我们开始吧。

步骤1. HTML (Step 1. HTML)

First, let’s prepare HTML markup for our game:

首先,让我们为游戏准备HTML标记:


    <!-- add styles -->
    <link href="css/main.css" rel="stylesheet" type="text/css" />
    <!-- add scripts -->
    <script src="http://code.jquery.com/jquery-1.7.1.min.js"></script>
    <script src="js/main.js"></script>
    <!-- This is where the game will be injected -->
    <div id="game_object"></div>

    <!-- add styles -->
    <link href="css/main.css" rel="stylesheet" type="text/css" />
    <!-- add scripts -->
    <script src="http://code.jquery.com/jquery-1.7.1.min.js"></script>
    <script src="js/main.js"></script>
    <!-- This is where the game will be injected -->
    <div id="game_object"></div>

步骤2. CSS (Step 2. CSS)

There are a few styles for our game:

我们的游戏有几种样式:

css / main.css (css/main.css)

#game_object {
    background-color: #ffffff;
    height: 705px;
    margin: 20px auto;
    position: relative;
    width: 705px;
}
#board div {
    background: url("../images/cat_face.jpg") no-repeat scroll 0 0 #ffffff;
    cursor: pointer;
    height: 175px;
    line-height: 175px;
    position: absolute;
    text-align: center;
    width: 175px;
    /* css3 shadow */
    -moz-box-shadow: inset 0 0 20px #555555;
    -webkit-box-shadow: inset 0 0 20px #555555;
    -ms-box-shadow: inset 0 0 20px #555555;
    -o-box-shadow: inset 0 0 20px #555555;
    box-shadow: inset 0 0 20px #555555;
}

#game_object {
    background-color: #ffffff;
    height: 705px;
    margin: 20px auto;
    position: relative;
    width: 705px;
}
#board div {
    background: url("../images/cat_face.jpg") no-repeat scroll 0 0 #ffffff;
    cursor: pointer;
    height: 175px;
    line-height: 175px;
    position: absolute;
    text-align: center;
    width: 175px;
    /* css3 shadow */
    -moz-box-shadow: inset 0 0 20px #555555;
    -webkit-box-shadow: inset 0 0 20px #555555;
    -ms-box-shadow: inset 0 0 20px #555555;
    -o-box-shadow: inset 0 0 20px #555555;
    box-shadow: inset 0 0 20px #555555;
}

步骤3. JS (Step 3. JS)

Now, the most interesting step – the game code (as jQuery plugin):

现在,最有趣的步骤是游戏代码(作为jQuery插件):

js / main.js (js/main.js)

// This is a JavaScript event. It means - once DOM is finished loading,
// execute everything inside the callback function scope
// This is where we initialize the game
$(document).ready(function() {
    // Initialize the game and create the plugin
    // When the squares swap places, the moving square must always appear on top
    var zi = 1; // We increment z-index each time a square is shifted
    // The index of the empty square by default, the 16th square
    var EmptySquare = 16;
    // Now, this is where we create the plugin and call it fifteen.
    $.fn.extend({ fifteen:
        function(square_size) {
            // Grab the id of the HTML element into which we are placing the game,
            // it is the selector - "#game_object" from  $("#game_object").fifteen(175);
            var gameObjectElement = '#' + $(this).attr('id');
            var sqSize = square_size + 'px';
            var boardSize = (square_size * 4) + 'px';
            // Inject DIV into game_object, this is our game board
            $(gameObjectElement).html('<div id="board"></div>');
            $('#board').css({ position:'absolute', width: boardSize, height: boardSize, border: '1px solid gray' });
            // Populate the game board's HTML container with 15 squares
            for (var i = 0; i < 16; i++) {
                // A dirty way to create an arbitrary DIV and append it into HTML dynamically
                // Notice each square uses the same image. It just uses a different x/y offset for each square
                $('#board').append("<div style='left: " + ((i % 4) * square_size) + "px; top: " + Math.floor(i / 4) * square_size + "px; width: " + square_size + "px; height: " + square_size + "px; background-position: " + (-(i % 4) * square_size) + "px " + -Math.floor(i / 4) * square_size + "px '></div>");
            }
            // Empty up the 16th square, as the starting point
            // EmptySquare = 16
            $('#board').children("div:nth-child(" + EmptySquare + ")").css({backgroundImage: "", background: "#ffffff"});
            // Attach click event to each square
            $('#board').children('div').click(function() {
                Move(this, square_size);
            });
        }
    });
    // Move() is the function that is called when a square is clicked
    // Note that it is independent of the plugin itself which is described above
    // It takes two parameters,
    //     1. object handle to the square that was clicked, and
    //     2. the width of the square
    function Move(clicked_square, square_size) {
        // We need to locate movable tiles based on where the empty spot is,
        // We can only move the four surrounding squares
        var movable = false;
        // Swap x/y between the clicked square and the currently empty square
        var oldx = $('#board').children("div:nth-child(" + EmptySquare + ")").css('left');
        var oldy = $('#board').children("div:nth-child(" + EmptySquare + ")").css('top');
        var newx = $(clicked_square).css('left');
        var newy = $(clicked_square).css('top');
        // The clicked square is north of the empty square
        if (oldx == newx && newy == (parseInt(oldy) - square_size) + 'px')
            movable = true;
        // The clicked square is south of the empty square
        if (oldx == newx && newy == (parseInt(oldy) + square_size) + 'px')
            movable = true;
        // The clicked square is west of the empty square
        if ((parseInt(oldx) - square_size) + 'px' == newx && newy == oldy)
            movable = true;
        // The clicked square is east of the empty square
        if ((parseInt(oldx) + square_size) + 'px' == newx && newy == oldy)
            movable = true;
        if (movable) {
            // Increment zindex so the new tile is always on top of all others
            $(clicked_square).css('z-index', zi++);
            // Swap squares... Animate new square into old square position
            $(clicked_square).animate({ left: oldx, top: oldy }, 200, function() {
                //Move old square into new square position
                $('#board').children("div:nth-child(" + EmptySquare + ")").css('left', newx);
                $('#board').children("div:nth-child(" + EmptySquare + ")").css('top', newy);
            });
        }
    }
    // Ok, we're ready to initialize the game, let's do it.
    // Create a game with 175 by 175 squares inside "#game_object" div:
    $('#game_object').fifteen(175);
});

// This is a JavaScript event. It means - once DOM is finished loading,
// execute everything inside the callback function scope
// This is where we initialize the game
$(document).ready(function() {
    // Initialize the game and create the plugin
    // When the squares swap places, the moving square must always appear on top
    var zi = 1; // We increment z-index each time a square is shifted
    // The index of the empty square by default, the 16th square
    var EmptySquare = 16;
    // Now, this is where we create the plugin and call it fifteen.
    $.fn.extend({ fifteen:
        function(square_size) {
            // Grab the id of the HTML element into which we are placing the game,
            // it is the selector - "#game_object" from  $("#game_object").fifteen(175);
            var gameObjectElement = '#' + $(this).attr('id');
            var sqSize = square_size + 'px';
            var boardSize = (square_size * 4) + 'px';
            // Inject DIV into game_object, this is our game board
            $(gameObjectElement).html('<div id="board"></div>');
            $('#board').css({ position:'absolute', width: boardSize, height: boardSize, border: '1px solid gray' });
            // Populate the game board's HTML container with 15 squares
            for (var i = 0; i < 16; i++) {
                // A dirty way to create an arbitrary DIV and append it into HTML dynamically
                // Notice each square uses the same image. It just uses a different x/y offset for each square
                $('#board').append("<div style='left: " + ((i % 4) * square_size) + "px; top: " + Math.floor(i / 4) * square_size + "px; width: " + square_size + "px; height: " + square_size + "px; background-position: " + (-(i % 4) * square_size) + "px " + -Math.floor(i / 4) * square_size + "px '></div>");
            }
            // Empty up the 16th square, as the starting point
            // EmptySquare = 16
            $('#board').children("div:nth-child(" + EmptySquare + ")").css({backgroundImage: "", background: "#ffffff"});
            // Attach click event to each square
            $('#board').children('div').click(function() {
                Move(this, square_size);
            });
        }
    });
    // Move() is the function that is called when a square is clicked
    // Note that it is independent of the plugin itself which is described above
    // It takes two parameters,
    //     1. object handle to the square that was clicked, and
    //     2. the width of the square
    function Move(clicked_square, square_size) {
        // We need to locate movable tiles based on where the empty spot is,
        // We can only move the four surrounding squares
        var movable = false;
        // Swap x/y between the clicked square and the currently empty square
        var oldx = $('#board').children("div:nth-child(" + EmptySquare + ")").css('left');
        var oldy = $('#board').children("div:nth-child(" + EmptySquare + ")").css('top');
        var newx = $(clicked_square).css('left');
        var newy = $(clicked_square).css('top');
        // The clicked square is north of the empty square
        if (oldx == newx && newy == (parseInt(oldy) - square_size) + 'px')
            movable = true;
        // The clicked square is south of the empty square
        if (oldx == newx && newy == (parseInt(oldy) + square_size) + 'px')
            movable = true;
        // The clicked square is west of the empty square
        if ((parseInt(oldx) - square_size) + 'px' == newx && newy == oldy)
            movable = true;
        // The clicked square is east of the empty square
        if ((parseInt(oldx) + square_size) + 'px' == newx && newy == oldy)
            movable = true;
        if (movable) {
            // Increment zindex so the new tile is always on top of all others
            $(clicked_square).css('z-index', zi++);
            // Swap squares... Animate new square into old square position
            $(clicked_square).animate({ left: oldx, top: oldy }, 200, function() {
                //Move old square into new square position
                $('#board').children("div:nth-child(" + EmptySquare + ")").css('left', newx);
                $('#board').children("div:nth-child(" + EmptySquare + ")").css('top', newy);
            });
        }
    }
    // Ok, we're ready to initialize the game, let's do it.
    // Create a game with 175 by 175 squares inside "#game_object" div:
    $('#game_object').fifteen(175);
});

I tried to explain the code to the best of my ability here but some details were skipped because there is so much more to JavaScript.

我试图在这里尽我所能来解释代码,但由于JavaScript的内容还很多,因此省略了一些细节。

If you feel like you still need to understand what some of the things mean I recommend grabbing a copy of my jquery tutorial book [2] which contains a multitude of tutorials and visual diagrams. They are designed to help you build your understanding of JavaScript and jQuery so you can write your own plugins, games, etc.

如果您觉得仍然需要了解某些含义,建议您拿一份我的jquery教程书[2]的副本,其中包含大量的教程和可视化图。 它们旨在帮助您建立对JavaScript和jQuery的理解,以便您可以编写自己的插件,游戏等。

现场演示

[sociallocker]

[社交储物柜]

打包下载

[/sociallocker]

[/ sociallocker]

结论 (Conclusion)

I hope you enjoyed this tutorial and perhaps learned a thing or two. Thanks for reading!

我希望您喜欢本教程,并且可能学到了一两个东西。 谢谢阅读!

Greg Sidelnikov

格雷格·西德尔尼科夫

翻译自: https://www.script-tutorials.com/how-to-create-a-game-using-jquery/

jquery创建a

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值